aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/Kconfig4
-rw-r--r--sound/soc/Makefile4
-rw-r--r--sound/soc/atmel/atmel-pcm-dma.c29
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.c54
-rw-r--r--sound/soc/au1x/ac97c.c9
-rw-r--r--sound/soc/au1x/i2sc.c9
-rw-r--r--sound/soc/au1x/psc-ac97.c9
-rw-r--r--sound/soc/au1x/psc-i2s.c9
-rw-r--r--sound/soc/blackfin/bf5xx-ac97.c9
-rw-r--r--sound/soc/blackfin/bf5xx-i2s.c9
-rw-r--r--sound/soc/blackfin/bf5xx-tdm.c9
-rw-r--r--sound/soc/blackfin/bf6xx-i2s.c9
-rw-r--r--sound/soc/cirrus/edb93xx.c1
-rw-r--r--sound/soc/cirrus/ep93xx-ac97.c18
-rw-r--r--sound/soc/cirrus/ep93xx-i2s.c25
-rw-r--r--sound/soc/cirrus/ep93xx-pcm.c38
-rw-r--r--sound/soc/cirrus/ep93xx-pcm.h20
-rw-r--r--sound/soc/cirrus/simone.c2
-rw-r--r--sound/soc/cirrus/snappercl15.c1
-rw-r--r--sound/soc/codecs/Kconfig10
-rw-r--r--sound/soc/codecs/Makefile4
-rw-r--r--sound/soc/codecs/adau1373.c5
-rw-r--r--sound/soc/codecs/ak4104.c55
-rw-r--r--sound/soc/codecs/ak5386.c152
-rw-r--r--sound/soc/codecs/arizona.c497
-rw-r--r--sound/soc/codecs/arizona.h31
-rw-r--r--sound/soc/codecs/cs4271.c166
-rw-r--r--sound/soc/codecs/cs42l73.c6
-rw-r--r--sound/soc/codecs/max98088.c32
-rw-r--r--sound/soc/codecs/max98090.c45
-rw-r--r--sound/soc/codecs/si476x.c47
-rw-r--r--sound/soc/codecs/tas5086.c591
-rw-r--r--sound/soc/codecs/wm0010.c6
-rw-r--r--sound/soc/codecs/wm2000.c4
-rw-r--r--sound/soc/codecs/wm2000.h2
-rw-r--r--sound/soc/codecs/wm2200.c2
-rw-r--r--sound/soc/codecs/wm5102.c121
-rw-r--r--sound/soc/codecs/wm5102.h6
-rw-r--r--sound/soc/codecs/wm5110.c46
-rw-r--r--sound/soc/codecs/wm5110.h6
-rw-r--r--sound/soc/codecs/wm8903.c4
-rw-r--r--sound/soc/codecs/wm8960.c10
-rw-r--r--sound/soc/codecs/wm8994.c68
-rw-r--r--sound/soc/codecs/wm8994.h3
-rw-r--r--sound/soc/codecs/wm_adsp.c124
-rw-r--r--sound/soc/codecs/wm_adsp.h5
-rw-r--r--sound/soc/codecs/wm_hubs.c9
-rw-r--r--sound/soc/davinci/davinci-i2s.c15
-rw-r--r--sound/soc/davinci/davinci-mcasp.c110
-rw-r--r--sound/soc/davinci/davinci-mcasp.h2
-rw-r--r--sound/soc/davinci/davinci-pcm.c9
-rw-r--r--sound/soc/davinci/davinci-vcif.c11
-rw-r--r--sound/soc/dwc/designware_i2s.c9
-rw-r--r--sound/soc/fsl/Kconfig2
-rw-r--r--sound/soc/fsl/fsl_ssi.c64
-rw-r--r--sound/soc/fsl/fsl_ssi.h8
-rw-r--r--sound/soc/fsl/imx-audmux.c3
-rw-r--r--sound/soc/fsl/imx-pcm-dma.c120
-rw-r--r--sound/soc/fsl/imx-pcm-fiq.c6
-rw-r--r--sound/soc/fsl/imx-pcm.c6
-rw-r--r--sound/soc/fsl/imx-pcm.h24
-rw-r--r--sound/soc/fsl/imx-sgtl5000.c2
-rw-r--r--sound/soc/fsl/imx-ssi.c62
-rw-r--r--sound/soc/fsl/imx-ssi.h7
-rw-r--r--sound/soc/fsl/mpc5200_psc_ac97.c8
-rw-r--r--sound/soc/fsl/mpc5200_psc_i2s.c9
-rw-r--r--sound/soc/jz4740/jz4740-i2s.c9
-rw-r--r--sound/soc/kirkwood/kirkwood-i2s.c11
-rw-r--r--sound/soc/mid-x86/sst_platform.c20
-rw-r--r--sound/soc/mid-x86/sst_platform.h2
-rw-r--r--sound/soc/mxs/Kconfig2
-rw-r--r--sound/soc/mxs/mxs-pcm.c176
-rw-r--r--sound/soc/mxs/mxs-pcm.h4
-rw-r--r--sound/soc/mxs/mxs-saif.c20
-rw-r--r--sound/soc/nuc900/nuc900-ac97.c9
-rw-r--r--sound/soc/omap/am3517evm.c1
-rw-r--r--sound/soc/omap/ams-delta.c1
-rw-r--r--sound/soc/omap/mcbsp.c14
-rw-r--r--sound/soc/omap/mcbsp.h7
-rw-r--r--sound/soc/omap/n810.c1
-rw-r--r--sound/soc/omap/omap-abe-twl6040.c1
-rw-r--r--sound/soc/omap/omap-dmic.c47
-rw-r--r--sound/soc/omap/omap-hdmi.c33
-rw-r--r--sound/soc/omap/omap-mcbsp.c27
-rw-r--r--sound/soc/omap/omap-mcpdm.c118
-rw-r--r--sound/soc/omap/omap-pcm.c86
-rw-r--r--sound/soc/omap/omap-pcm.h40
-rw-r--r--sound/soc/omap/omap-twl4030.c1
-rw-r--r--sound/soc/omap/omap3pandora.c9
-rw-r--r--sound/soc/omap/osk5912.c1
-rw-r--r--sound/soc/omap/rx51.c1
-rw-r--r--sound/soc/pxa/mmp-pcm.c34
-rw-r--r--sound/soc/pxa/mmp-sspa.c9
-rw-r--r--sound/soc/pxa/pxa-ssp.c9
-rw-r--r--sound/soc/pxa/pxa2xx-ac97.c11
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c9
-rw-r--r--sound/soc/s6000/s6000-i2s.c9
-rw-r--r--sound/soc/samsung/Kconfig5
-rw-r--r--sound/soc/samsung/ac97.c14
-rw-r--r--sound/soc/samsung/goni_wm8994.c11
-rw-r--r--sound/soc/samsung/h1940_uda1380.c2
-rw-r--r--sound/soc/samsung/i2s.c16
-rw-r--r--sound/soc/samsung/idma.c11
-rw-r--r--sound/soc/samsung/neo1973_wm8753.c3
-rw-r--r--sound/soc/samsung/pcm.c11
-rw-r--r--sound/soc/samsung/regs-ac97.h67
-rw-r--r--sound/soc/samsung/regs-iis.h70
-rw-r--r--sound/soc/samsung/rx1950_uda1380.c2
-rw-r--r--sound/soc/samsung/s3c-i2s-v2.c9
-rw-r--r--sound/soc/samsung/s3c-i2s-v2.h7
-rw-r--r--sound/soc/samsung/s3c2412-i2s.c12
-rw-r--r--sound/soc/samsung/s3c24xx-i2s.c13
-rw-r--r--sound/soc/samsung/s3c24xx_uda134x.c2
-rw-r--r--sound/soc/samsung/spdif.c11
-rw-r--r--sound/soc/sh/fsi.c14
-rw-r--r--sound/soc/sh/hac.c10
-rw-r--r--sound/soc/sh/migor.c2
-rw-r--r--sound/soc/sh/siu_dai.c11
-rw-r--r--sound/soc/sh/ssi.c10
-rw-r--r--sound/soc/soc-compress.c38
-rw-r--r--sound/soc/soc-core.c213
-rw-r--r--sound/soc/soc-dapm.c320
-rw-r--r--sound/soc/soc-dmaengine-pcm.c150
-rw-r--r--sound/soc/soc-generic-dmaengine-pcm.c300
-rw-r--r--sound/soc/soc-io.c5
-rw-r--r--sound/soc/soc-utils.c25
-rw-r--r--sound/soc/spear/spdif_in.c9
-rw-r--r--sound/soc/spear/spdif_out.c9
-rw-r--r--sound/soc/spear/spear_pcm.c23
-rw-r--r--sound/soc/tegra/Kconfig2
-rw-r--r--sound/soc/tegra/tegra20_ac97.c28
-rw-r--r--sound/soc/tegra/tegra20_ac97.h4
-rw-r--r--sound/soc/tegra/tegra20_i2s.c28
-rw-r--r--sound/soc/tegra/tegra20_i2s.h4
-rw-r--r--sound/soc/tegra/tegra20_spdif.c22
-rw-r--r--sound/soc/tegra/tegra20_spdif.h4
-rw-r--r--sound/soc/tegra/tegra30_ahub.c72
-rw-r--r--sound/soc/tegra/tegra30_ahub.h24
-rw-r--r--sound/soc/tegra/tegra30_i2s.c28
-rw-r--r--sound/soc/tegra/tegra30_i2s.h4
-rw-r--r--sound/soc/tegra/tegra_alc5632.c15
-rw-r--r--sound/soc/tegra/tegra_asoc_utils.c34
-rw-r--r--sound/soc/tegra/tegra_asoc_utils.h1
-rw-r--r--sound/soc/tegra/tegra_pcm.c187
-rw-r--r--sound/soc/tegra/tegra_pcm.h7
-rw-r--r--sound/soc/tegra/tegra_wm8753.c15
-rw-r--r--sound/soc/tegra/tegra_wm8903.c179
-rw-r--r--sound/soc/tegra/tegra_wm9712.c7
-rw-r--r--sound/soc/tegra/trimslice.c56
-rw-r--r--sound/soc/txx9/txx9aclc-ac97.c9
-rw-r--r--sound/soc/ux500/Kconfig2
-rw-r--r--sound/soc/ux500/ux500_msp_dai.c13
-rw-r--r--sound/soc/ux500/ux500_msp_dai.h5
-rw-r--r--sound/soc/ux500/ux500_msp_i2s.h1
-rw-r--r--sound/soc/ux500/ux500_pcm.c229
-rw-r--r--sound/soc/ux500/ux500_pcm.h14
156 files changed, 3807 insertions, 2116 deletions
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 5da8ca7aee05..9e675c76436c 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -29,6 +29,10 @@ config SND_SOC_AC97_BUS
29config SND_SOC_DMAENGINE_PCM 29config SND_SOC_DMAENGINE_PCM
30 bool 30 bool
31 31
32config SND_SOC_GENERIC_DMAENGINE_PCM
33 bool
34 select SND_SOC_DMAENGINE_PCM
35
32# All the supported SoCs 36# All the supported SoCs
33source "sound/soc/atmel/Kconfig" 37source "sound/soc/atmel/Kconfig"
34source "sound/soc/au1x/Kconfig" 38source "sound/soc/au1x/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 99f32f7c0692..197b6ae54c8d 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -5,6 +5,10 @@ ifneq ($(CONFIG_SND_SOC_DMAENGINE_PCM),)
5snd-soc-core-objs += soc-dmaengine-pcm.o 5snd-soc-core-objs += soc-dmaengine-pcm.o
6endif 6endif
7 7
8ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),)
9snd-soc-core-objs += soc-generic-dmaengine-pcm.o
10endif
11
8obj-$(CONFIG_SND_SOC) += snd-soc-core.o 12obj-$(CONFIG_SND_SOC) += snd-soc-core.o
9obj-$(CONFIG_SND_SOC) += codecs/ 13obj-$(CONFIG_SND_SOC) += codecs/
10obj-$(CONFIG_SND_SOC) += generic/ 14obj-$(CONFIG_SND_SOC) += generic/
diff --git a/sound/soc/atmel/atmel-pcm-dma.c b/sound/soc/atmel/atmel-pcm-dma.c
index 30184a4a147a..1d38fd0bc4e2 100644
--- a/sound/soc/atmel/atmel-pcm-dma.c
+++ b/sound/soc/atmel/atmel-pcm-dma.c
@@ -67,9 +67,10 @@ static const struct snd_pcm_hardware atmel_pcm_dma_hardware = {
67static void atmel_pcm_dma_irq(u32 ssc_sr, 67static void atmel_pcm_dma_irq(u32 ssc_sr,
68 struct snd_pcm_substream *substream) 68 struct snd_pcm_substream *substream)
69{ 69{
70 struct snd_soc_pcm_runtime *rtd = substream->private_data;
70 struct atmel_pcm_dma_params *prtd; 71 struct atmel_pcm_dma_params *prtd;
71 72
72 prtd = snd_dmaengine_pcm_get_data(substream); 73 prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
73 74
74 if (ssc_sr & prtd->mask->ssc_error) { 75 if (ssc_sr & prtd->mask->ssc_error) {
75 if (snd_pcm_running(substream)) 76 if (snd_pcm_running(substream))
@@ -104,15 +105,13 @@ static bool filter(struct dma_chan *chan, void *slave)
104} 105}
105 106
106static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream, 107static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream,
107 struct snd_pcm_hw_params *params) 108 struct snd_pcm_hw_params *params, struct atmel_pcm_dma_params *prtd)
108{ 109{
109 struct atmel_pcm_dma_params *prtd;
110 struct ssc_device *ssc; 110 struct ssc_device *ssc;
111 struct dma_chan *dma_chan; 111 struct dma_chan *dma_chan;
112 struct dma_slave_config slave_config; 112 struct dma_slave_config slave_config;
113 int ret; 113 int ret;
114 114
115 prtd = snd_dmaengine_pcm_get_data(substream);
116 ssc = prtd->ssc; 115 ssc = prtd->ssc;
117 116
118 ret = snd_hwparams_to_dma_slave_config(substream, params, 117 ret = snd_hwparams_to_dma_slave_config(substream, params,
@@ -130,8 +129,6 @@ static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream,
130 slave_config.src_maxburst = 1; 129 slave_config.src_maxburst = 1;
131 } 130 }
132 131
133 slave_config.device_fc = false;
134
135 dma_chan = snd_dmaengine_pcm_get_chan(substream); 132 dma_chan = snd_dmaengine_pcm_get_chan(substream);
136 if (dmaengine_slave_config(dma_chan, &slave_config)) { 133 if (dmaengine_slave_config(dma_chan, &slave_config)) {
137 pr_err("atmel-pcm: failed to configure dma channel\n"); 134 pr_err("atmel-pcm: failed to configure dma channel\n");
@@ -158,15 +155,13 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
158 if (ssc->pdev) 155 if (ssc->pdev)
159 sdata = ssc->pdev->dev.platform_data; 156 sdata = ssc->pdev->dev.platform_data;
160 157
161 ret = snd_dmaengine_pcm_open(substream, filter, sdata); 158 ret = snd_dmaengine_pcm_open_request_chan(substream, filter, sdata);
162 if (ret) { 159 if (ret) {
163 pr_err("atmel-pcm: dmaengine pcm open failed\n"); 160 pr_err("atmel-pcm: dmaengine pcm open failed\n");
164 return -EINVAL; 161 return -EINVAL;
165 } 162 }
166 163
167 snd_dmaengine_pcm_set_data(substream, prtd); 164 ret = atmel_pcm_configure_dma(substream, params, prtd);
168
169 ret = atmel_pcm_configure_dma(substream, params);
170 if (ret) { 165 if (ret) {
171 pr_err("atmel-pcm: failed to configure dmai\n"); 166 pr_err("atmel-pcm: failed to configure dmai\n");
172 goto err; 167 goto err;
@@ -176,15 +171,16 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
176 171
177 return 0; 172 return 0;
178err: 173err:
179 snd_dmaengine_pcm_close(substream); 174 snd_dmaengine_pcm_close_release_chan(substream);
180 return ret; 175 return ret;
181} 176}
182 177
183static int atmel_pcm_dma_prepare(struct snd_pcm_substream *substream) 178static int atmel_pcm_dma_prepare(struct snd_pcm_substream *substream)
184{ 179{
180 struct snd_soc_pcm_runtime *rtd = substream->private_data;
185 struct atmel_pcm_dma_params *prtd; 181 struct atmel_pcm_dma_params *prtd;
186 182
187 prtd = snd_dmaengine_pcm_get_data(substream); 183 prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
188 184
189 ssc_writex(prtd->ssc->regs, SSC_IER, prtd->mask->ssc_error); 185 ssc_writex(prtd->ssc->regs, SSC_IER, prtd->mask->ssc_error);
190 ssc_writex(prtd->ssc->regs, SSC_CR, prtd->mask->ssc_enable); 186 ssc_writex(prtd->ssc->regs, SSC_CR, prtd->mask->ssc_enable);
@@ -199,16 +195,9 @@ static int atmel_pcm_open(struct snd_pcm_substream *substream)
199 return 0; 195 return 0;
200} 196}
201 197
202static int atmel_pcm_close(struct snd_pcm_substream *substream)
203{
204 snd_dmaengine_pcm_close(substream);
205
206 return 0;
207}
208
209static struct snd_pcm_ops atmel_pcm_ops = { 198static struct snd_pcm_ops atmel_pcm_ops = {
210 .open = atmel_pcm_open, 199 .open = atmel_pcm_open,
211 .close = atmel_pcm_close, 200 .close = snd_dmaengine_pcm_close_release_chan,
212 .ioctl = snd_pcm_lib_ioctl, 201 .ioctl = snd_pcm_lib_ioctl,
213 .hw_params = atmel_pcm_hw_params, 202 .hw_params = atmel_pcm_hw_params,
214 .prepare = atmel_pcm_dma_prepare, 203 .prepare = atmel_pcm_dma_prepare,
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
index e13580d6c476..f3fdfa07fcb9 100644
--- a/sound/soc/atmel/atmel_ssc_dai.c
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -533,6 +533,49 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
533 break; 533 break;
534 534
535 case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM: 535 case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
536 /*
537 * DSP/PCM Mode A format, CODEC supplies BCLK and LRC clocks.
538 *
539 * The SSC transmit clock is obtained from the BCLK signal on
540 * on the TK line, and the SSC receive clock is
541 * generated from the transmit clock.
542 *
543 * Data is transferred on first BCLK after LRC pulse rising
544 * edge.If stereo, the right channel data is contiguous with
545 * the left channel data.
546 */
547 rcmr = SSC_BF(RCMR_PERIOD, 0)
548 | SSC_BF(RCMR_STTDLY, START_DELAY)
549 | SSC_BF(RCMR_START, SSC_START_RISING_RF)
550 | SSC_BF(RCMR_CKI, SSC_CKI_RISING)
551 | SSC_BF(RCMR_CKO, SSC_CKO_NONE)
552 | SSC_BF(RCMR_CKS, SSC_CKS_PIN);
553
554 rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
555 | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE)
556 | SSC_BF(RFMR_FSLEN, 0)
557 | SSC_BF(RFMR_DATNB, (channels - 1))
558 | SSC_BIT(RFMR_MSBF)
559 | SSC_BF(RFMR_LOOP, 0)
560 | SSC_BF(RFMR_DATLEN, (bits - 1));
561
562 tcmr = SSC_BF(TCMR_PERIOD, 0)
563 | SSC_BF(TCMR_STTDLY, START_DELAY)
564 | SSC_BF(TCMR_START, SSC_START_RISING_RF)
565 | SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
566 | SSC_BF(TCMR_CKO, SSC_CKO_NONE)
567 | SSC_BF(TCMR_CKS, SSC_CKS_PIN);
568
569 tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
570 | SSC_BF(TFMR_FSDEN, 0)
571 | SSC_BF(TFMR_FSOS, SSC_FSOS_NONE)
572 | SSC_BF(TFMR_FSLEN, 0)
573 | SSC_BF(TFMR_DATNB, (channels - 1))
574 | SSC_BIT(TFMR_MSBF)
575 | SSC_BF(TFMR_DATDEF, 0)
576 | SSC_BF(TFMR_DATLEN, (bits - 1));
577 break;
578
536 default: 579 default:
537 printk(KERN_WARNING "atmel_ssc_dai: unsupported DAI format 0x%x\n", 580 printk(KERN_WARNING "atmel_ssc_dai: unsupported DAI format 0x%x\n",
538 ssc_p->daifmt); 581 ssc_p->daifmt);
@@ -707,13 +750,18 @@ static struct snd_soc_dai_driver atmel_ssc_dai = {
707 .ops = &atmel_ssc_dai_ops, 750 .ops = &atmel_ssc_dai_ops,
708}; 751};
709 752
753static const struct snd_soc_component_driver atmel_ssc_component = {
754 .name = "atmel-ssc",
755};
756
710static int asoc_ssc_init(struct device *dev) 757static int asoc_ssc_init(struct device *dev)
711{ 758{
712 struct platform_device *pdev = to_platform_device(dev); 759 struct platform_device *pdev = to_platform_device(dev);
713 struct ssc_device *ssc = platform_get_drvdata(pdev); 760 struct ssc_device *ssc = platform_get_drvdata(pdev);
714 int ret; 761 int ret;
715 762
716 ret = snd_soc_register_dai(dev, &atmel_ssc_dai); 763 ret = snd_soc_register_component(dev, &atmel_ssc_component,
764 &atmel_ssc_dai, 1);
717 if (ret) { 765 if (ret) {
718 dev_err(dev, "Could not register DAI: %d\n", ret); 766 dev_err(dev, "Could not register DAI: %d\n", ret);
719 goto err; 767 goto err;
@@ -732,7 +780,7 @@ static int asoc_ssc_init(struct device *dev)
732 return 0; 780 return 0;
733 781
734err_unregister_dai: 782err_unregister_dai:
735 snd_soc_unregister_dai(dev); 783 snd_soc_unregister_component(dev);
736err: 784err:
737 return ret; 785 return ret;
738} 786}
@@ -747,7 +795,7 @@ static void asoc_ssc_exit(struct device *dev)
747 else 795 else
748 atmel_pcm_pdc_platform_unregister(dev); 796 atmel_pcm_pdc_platform_unregister(dev);
749 797
750 snd_soc_unregister_dai(dev); 798 snd_soc_unregister_component(dev);
751} 799}
752 800
753/** 801/**
diff --git a/sound/soc/au1x/ac97c.c b/sound/soc/au1x/ac97c.c
index ea7d9d157022..44b8dcecf571 100644
--- a/sound/soc/au1x/ac97c.c
+++ b/sound/soc/au1x/ac97c.c
@@ -223,6 +223,10 @@ static struct snd_soc_dai_driver au1xac97c_dai_driver = {
223 .ops = &alchemy_ac97c_ops, 223 .ops = &alchemy_ac97c_ops,
224}; 224};
225 225
226static const struct snd_soc_component_driver au1xac97c_component = {
227 .name = "au1xac97c",
228};
229
226static int au1xac97c_drvprobe(struct platform_device *pdev) 230static int au1xac97c_drvprobe(struct platform_device *pdev)
227{ 231{
228 int ret; 232 int ret;
@@ -268,7 +272,8 @@ static int au1xac97c_drvprobe(struct platform_device *pdev)
268 272
269 platform_set_drvdata(pdev, ctx); 273 platform_set_drvdata(pdev, ctx);
270 274
271 ret = snd_soc_register_dai(&pdev->dev, &au1xac97c_dai_driver); 275 ret = snd_soc_register_component(&pdev->dev, &au1xac97c_component,
276 &au1xac97c_dai_driver, 1);
272 if (ret) 277 if (ret)
273 return ret; 278 return ret;
274 279
@@ -280,7 +285,7 @@ static int au1xac97c_drvremove(struct platform_device *pdev)
280{ 285{
281 struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev); 286 struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev);
282 287
283 snd_soc_unregister_dai(&pdev->dev); 288 snd_soc_unregister_component(&pdev->dev);
284 289
285 WR(ctx, AC97_ENABLE, EN_D); /* clock off, disable */ 290 WR(ctx, AC97_ENABLE, EN_D); /* clock off, disable */
286 291
diff --git a/sound/soc/au1x/i2sc.c b/sound/soc/au1x/i2sc.c
index 072448afc219..b3f37f6edbcb 100644
--- a/sound/soc/au1x/i2sc.c
+++ b/sound/soc/au1x/i2sc.c
@@ -225,6 +225,10 @@ static struct snd_soc_dai_driver au1xi2s_dai_driver = {
225 .ops = &au1xi2s_dai_ops, 225 .ops = &au1xi2s_dai_ops,
226}; 226};
227 227
228static const struct snd_soc_component_driver au1xi2s_component = {
229 .name = "au1xi2s",
230};
231
228static int au1xi2s_drvprobe(struct platform_device *pdev) 232static int au1xi2s_drvprobe(struct platform_device *pdev)
229{ 233{
230 struct resource *iores, *dmares; 234 struct resource *iores, *dmares;
@@ -260,14 +264,15 @@ static int au1xi2s_drvprobe(struct platform_device *pdev)
260 264
261 platform_set_drvdata(pdev, ctx); 265 platform_set_drvdata(pdev, ctx);
262 266
263 return snd_soc_register_dai(&pdev->dev, &au1xi2s_dai_driver); 267 return snd_soc_register_component(&pdev->dev, &au1xi2s_component,
268 &au1xi2s_dai_driver, 1);
264} 269}
265 270
266static int au1xi2s_drvremove(struct platform_device *pdev) 271static int au1xi2s_drvremove(struct platform_device *pdev)
267{ 272{
268 struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev); 273 struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev);
269 274
270 snd_soc_unregister_dai(&pdev->dev); 275 snd_soc_unregister_component(&pdev->dev);
271 276
272 WR(ctx, I2S_ENABLE, EN_D); /* clock off, disable */ 277 WR(ctx, I2S_ENABLE, EN_D); /* clock off, disable */
273 278
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c
index 6ba07e365967..8f1862aa7333 100644
--- a/sound/soc/au1x/psc-ac97.c
+++ b/sound/soc/au1x/psc-ac97.c
@@ -361,6 +361,10 @@ static const struct snd_soc_dai_driver au1xpsc_ac97_dai_template = {
361 .ops = &au1xpsc_ac97_dai_ops, 361 .ops = &au1xpsc_ac97_dai_ops,
362}; 362};
363 363
364static const struct snd_soc_component_driver au1xpsc_ac97_component = {
365 .name = "au1xpsc-ac97",
366};
367
364static int au1xpsc_ac97_drvprobe(struct platform_device *pdev) 368static int au1xpsc_ac97_drvprobe(struct platform_device *pdev)
365{ 369{
366 int ret; 370 int ret;
@@ -419,7 +423,8 @@ static int au1xpsc_ac97_drvprobe(struct platform_device *pdev)
419 423
420 platform_set_drvdata(pdev, wd); 424 platform_set_drvdata(pdev, wd);
421 425
422 ret = snd_soc_register_dai(&pdev->dev, &wd->dai_drv); 426 ret = snd_soc_register_component(&pdev->dev, &au1xpsc_ac97_component,
427 &wd->dai_drv, 1);
423 if (ret) 428 if (ret)
424 return ret; 429 return ret;
425 430
@@ -431,7 +436,7 @@ static int au1xpsc_ac97_drvremove(struct platform_device *pdev)
431{ 436{
432 struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev); 437 struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
433 438
434 snd_soc_unregister_dai(&pdev->dev); 439 snd_soc_unregister_component(&pdev->dev);
435 440
436 /* disable PSC completely */ 441 /* disable PSC completely */
437 au_writel(0, AC97_CFG(wd)); 442 au_writel(0, AC97_CFG(wd));
diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c
index 360b4e50d7c8..fe923a7bdc39 100644
--- a/sound/soc/au1x/psc-i2s.c
+++ b/sound/soc/au1x/psc-i2s.c
@@ -288,6 +288,10 @@ static const struct snd_soc_dai_driver au1xpsc_i2s_dai_template = {
288 .ops = &au1xpsc_i2s_dai_ops, 288 .ops = &au1xpsc_i2s_dai_ops,
289}; 289};
290 290
291static const struct snd_soc_component_driver au1xpsc_i2s_component = {
292 .name = "au1xpsc-i2s",
293};
294
291static int au1xpsc_i2s_drvprobe(struct platform_device *pdev) 295static int au1xpsc_i2s_drvprobe(struct platform_device *pdev)
292{ 296{
293 struct resource *iores, *dmares; 297 struct resource *iores, *dmares;
@@ -350,14 +354,15 @@ static int au1xpsc_i2s_drvprobe(struct platform_device *pdev)
350 354
351 platform_set_drvdata(pdev, wd); 355 platform_set_drvdata(pdev, wd);
352 356
353 return snd_soc_register_dai(&pdev->dev, &wd->dai_drv); 357 return snd_soc_register_component(&pdev->dev, &au1xpsc_i2s_component,
358 &wd->dai_drv, 1);
354} 359}
355 360
356static int au1xpsc_i2s_drvremove(struct platform_device *pdev) 361static int au1xpsc_i2s_drvremove(struct platform_device *pdev)
357{ 362{
358 struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev); 363 struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
359 364
360 snd_soc_unregister_dai(&pdev->dev); 365 snd_soc_unregister_component(&pdev->dev);
361 366
362 au_writel(0, I2S_CFG(wd)); 367 au_writel(0, I2S_CFG(wd));
363 au_sync(); 368 au_sync();
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c
index 8e41bcb020eb..490217325975 100644
--- a/sound/soc/blackfin/bf5xx-ac97.c
+++ b/sound/soc/blackfin/bf5xx-ac97.c
@@ -282,6 +282,10 @@ static struct snd_soc_dai_driver bfin_ac97_dai = {
282 .formats = SNDRV_PCM_FMTBIT_S16_LE, }, 282 .formats = SNDRV_PCM_FMTBIT_S16_LE, },
283}; 283};
284 284
285static const struct snd_soc_component_driver bfin_ac97_component = {
286 .name = "bfin-ac97",
287};
288
285static int asoc_bfin_ac97_probe(struct platform_device *pdev) 289static int asoc_bfin_ac97_probe(struct platform_device *pdev)
286{ 290{
287 struct sport_device *sport_handle; 291 struct sport_device *sport_handle;
@@ -331,7 +335,8 @@ static int asoc_bfin_ac97_probe(struct platform_device *pdev)
331 goto sport_config_err; 335 goto sport_config_err;
332 } 336 }
333 337
334 ret = snd_soc_register_dai(&pdev->dev, &bfin_ac97_dai); 338 ret = snd_soc_register_component(&pdev->dev, &bfin_ac97_component,
339 &bfin_ac97_dai, 1);
335 if (ret) { 340 if (ret) {
336 pr_err("Failed to register DAI: %d\n", ret); 341 pr_err("Failed to register DAI: %d\n", ret);
337 goto sport_config_err; 342 goto sport_config_err;
@@ -356,7 +361,7 @@ static int asoc_bfin_ac97_remove(struct platform_device *pdev)
356{ 361{
357 struct sport_device *sport_handle = platform_get_drvdata(pdev); 362 struct sport_device *sport_handle = platform_get_drvdata(pdev);
358 363
359 snd_soc_unregister_dai(&pdev->dev); 364 snd_soc_unregister_component(&pdev->dev);
360 sport_done(sport_handle); 365 sport_done(sport_handle);
361#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET 366#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
362 gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); 367 gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c
index 168d88bccb41..dd0c2a4f83a3 100644
--- a/sound/soc/blackfin/bf5xx-i2s.c
+++ b/sound/soc/blackfin/bf5xx-i2s.c
@@ -245,6 +245,10 @@ static struct snd_soc_dai_driver bf5xx_i2s_dai = {
245 .ops = &bf5xx_i2s_dai_ops, 245 .ops = &bf5xx_i2s_dai_ops,
246}; 246};
247 247
248static const struct snd_soc_component_driver bf5xx_i2s_component = {
249 .name = "bf5xx-i2s",
250};
251
248static int bf5xx_i2s_probe(struct platform_device *pdev) 252static int bf5xx_i2s_probe(struct platform_device *pdev)
249{ 253{
250 struct sport_device *sport_handle; 254 struct sport_device *sport_handle;
@@ -257,7 +261,8 @@ static int bf5xx_i2s_probe(struct platform_device *pdev)
257 return -ENODEV; 261 return -ENODEV;
258 262
259 /* register with the ASoC layers */ 263 /* register with the ASoC layers */
260 ret = snd_soc_register_dai(&pdev->dev, &bf5xx_i2s_dai); 264 ret = snd_soc_register_component(&pdev->dev, &bf5xx_i2s_component,
265 &bf5xx_i2s_dai, 1);
261 if (ret) { 266 if (ret) {
262 pr_err("Failed to register DAI: %d\n", ret); 267 pr_err("Failed to register DAI: %d\n", ret);
263 sport_done(sport_handle); 268 sport_done(sport_handle);
@@ -273,7 +278,7 @@ static int bf5xx_i2s_remove(struct platform_device *pdev)
273 278
274 pr_debug("%s enter\n", __func__); 279 pr_debug("%s enter\n", __func__);
275 280
276 snd_soc_unregister_dai(&pdev->dev); 281 snd_soc_unregister_component(&pdev->dev);
277 sport_done(sport_handle); 282 sport_done(sport_handle);
278 283
279 return 0; 284 return 0;
diff --git a/sound/soc/blackfin/bf5xx-tdm.c b/sound/soc/blackfin/bf5xx-tdm.c
index c1e516ec53ad..69e9a3e935bd 100644
--- a/sound/soc/blackfin/bf5xx-tdm.c
+++ b/sound/soc/blackfin/bf5xx-tdm.c
@@ -249,6 +249,10 @@ static struct snd_soc_dai_driver bf5xx_tdm_dai = {
249 .ops = &bf5xx_tdm_dai_ops, 249 .ops = &bf5xx_tdm_dai_ops,
250}; 250};
251 251
252static const struct snd_soc_component_driver bf5xx_tdm_component = {
253 .name = "bf5xx-tdm",
254};
255
252static int bfin_tdm_probe(struct platform_device *pdev) 256static int bfin_tdm_probe(struct platform_device *pdev)
253{ 257{
254 struct sport_device *sport_handle; 258 struct sport_device *sport_handle;
@@ -282,7 +286,8 @@ static int bfin_tdm_probe(struct platform_device *pdev)
282 goto sport_config_err; 286 goto sport_config_err;
283 } 287 }
284 288
285 ret = snd_soc_register_dai(&pdev->dev, &bf5xx_tdm_dai); 289 ret = snd_soc_register_component(&pdev->dev, &bf5xx_tdm_component,
290 &bf5xx_tdm_dai, 1);
286 if (ret) { 291 if (ret) {
287 pr_err("Failed to register DAI: %d\n", ret); 292 pr_err("Failed to register DAI: %d\n", ret);
288 goto sport_config_err; 293 goto sport_config_err;
@@ -299,7 +304,7 @@ static int bfin_tdm_remove(struct platform_device *pdev)
299{ 304{
300 struct sport_device *sport_handle = platform_get_drvdata(pdev); 305 struct sport_device *sport_handle = platform_get_drvdata(pdev);
301 306
302 snd_soc_unregister_dai(&pdev->dev); 307 snd_soc_unregister_component(&pdev->dev);
303 sport_done(sport_handle); 308 sport_done(sport_handle);
304 309
305 return 0; 310 return 0;
diff --git a/sound/soc/blackfin/bf6xx-i2s.c b/sound/soc/blackfin/bf6xx-i2s.c
index 8f337972f438..c02405cc007d 100644
--- a/sound/soc/blackfin/bf6xx-i2s.c
+++ b/sound/soc/blackfin/bf6xx-i2s.c
@@ -186,6 +186,10 @@ static struct snd_soc_dai_driver bfin_i2s_dai = {
186 .ops = &bfin_i2s_dai_ops, 186 .ops = &bfin_i2s_dai_ops,
187}; 187};
188 188
189static const struct snd_soc_component_driver bfin_i2s_component = {
190 .name = "bfin-i2s",
191};
192
189static int bfin_i2s_probe(struct platform_device *pdev) 193static int bfin_i2s_probe(struct platform_device *pdev)
190{ 194{
191 struct sport_device *sport; 195 struct sport_device *sport;
@@ -197,7 +201,8 @@ static int bfin_i2s_probe(struct platform_device *pdev)
197 return -ENODEV; 201 return -ENODEV;
198 202
199 /* register with the ASoC layers */ 203 /* register with the ASoC layers */
200 ret = snd_soc_register_dai(dev, &bfin_i2s_dai); 204 ret = snd_soc_register_component(dev, &bfin_i2s_component,
205 &bfin_i2s_dai, 1);
201 if (ret) { 206 if (ret) {
202 dev_err(dev, "Failed to register DAI: %d\n", ret); 207 dev_err(dev, "Failed to register DAI: %d\n", ret);
203 sport_delete(sport); 208 sport_delete(sport);
@@ -212,7 +217,7 @@ static int bfin_i2s_remove(struct platform_device *pdev)
212{ 217{
213 struct sport_device *sport = platform_get_drvdata(pdev); 218 struct sport_device *sport = platform_get_drvdata(pdev);
214 219
215 snd_soc_unregister_dai(&pdev->dev); 220 snd_soc_unregister_component(&pdev->dev);
216 sport_delete(sport); 221 sport_delete(sport);
217 222
218 return 0; 223 return 0;
diff --git a/sound/soc/cirrus/edb93xx.c b/sound/soc/cirrus/edb93xx.c
index 5db68cf7b281..c43fb214558a 100644
--- a/sound/soc/cirrus/edb93xx.c
+++ b/sound/soc/cirrus/edb93xx.c
@@ -27,7 +27,6 @@
27#include <sound/soc.h> 27#include <sound/soc.h>
28#include <asm/mach-types.h> 28#include <asm/mach-types.h>
29#include <mach/hardware.h> 29#include <mach/hardware.h>
30#include "ep93xx-pcm.h"
31 30
32static int edb93xx_hw_params(struct snd_pcm_substream *substream, 31static int edb93xx_hw_params(struct snd_pcm_substream *substream,
33 struct snd_pcm_hw_params *params) 32 struct snd_pcm_hw_params *params)
diff --git a/sound/soc/cirrus/ep93xx-ac97.c b/sound/soc/cirrus/ep93xx-ac97.c
index 1738d28fb04f..7798fbd5e81d 100644
--- a/sound/soc/cirrus/ep93xx-ac97.c
+++ b/sound/soc/cirrus/ep93xx-ac97.c
@@ -23,7 +23,6 @@
23#include <sound/soc.h> 23#include <sound/soc.h>
24 24
25#include <linux/platform_data/dma-ep93xx.h> 25#include <linux/platform_data/dma-ep93xx.h>
26#include "ep93xx-pcm.h"
27 26
28/* 27/*
29 * Per channel (1-4) registers. 28 * Per channel (1-4) registers.
@@ -101,14 +100,16 @@ struct ep93xx_ac97_info {
101/* currently ALSA only supports a single AC97 device */ 100/* currently ALSA only supports a single AC97 device */
102static struct ep93xx_ac97_info *ep93xx_ac97_info; 101static struct ep93xx_ac97_info *ep93xx_ac97_info;
103 102
104static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_out = { 103static struct ep93xx_dma_data ep93xx_ac97_pcm_out = {
105 .name = "ac97-pcm-out", 104 .name = "ac97-pcm-out",
106 .dma_port = EP93XX_DMA_AAC1, 105 .dma_port = EP93XX_DMA_AAC1,
106 .direction = DMA_MEM_TO_DEV,
107}; 107};
108 108
109static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_in = { 109static struct ep93xx_dma_data ep93xx_ac97_pcm_in = {
110 .name = "ac97-pcm-in", 110 .name = "ac97-pcm-in",
111 .dma_port = EP93XX_DMA_AAC1, 111 .dma_port = EP93XX_DMA_AAC1,
112 .direction = DMA_DEV_TO_MEM,
112}; 113};
113 114
114static inline unsigned ep93xx_ac97_read_reg(struct ep93xx_ac97_info *info, 115static inline unsigned ep93xx_ac97_read_reg(struct ep93xx_ac97_info *info,
@@ -316,7 +317,7 @@ static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream,
316static int ep93xx_ac97_startup(struct snd_pcm_substream *substream, 317static int ep93xx_ac97_startup(struct snd_pcm_substream *substream,
317 struct snd_soc_dai *dai) 318 struct snd_soc_dai *dai)
318{ 319{
319 struct ep93xx_pcm_dma_params *dma_data; 320 struct ep93xx_dma_data *dma_data;
320 321
321 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 322 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
322 dma_data = &ep93xx_ac97_pcm_out; 323 dma_data = &ep93xx_ac97_pcm_out;
@@ -353,6 +354,10 @@ static struct snd_soc_dai_driver ep93xx_ac97_dai = {
353 .ops = &ep93xx_ac97_dai_ops, 354 .ops = &ep93xx_ac97_dai_ops,
354}; 355};
355 356
357static const struct snd_soc_component_driver ep93xx_ac97_component = {
358 .name = "ep93xx-ac97",
359};
360
356static int ep93xx_ac97_probe(struct platform_device *pdev) 361static int ep93xx_ac97_probe(struct platform_device *pdev)
357{ 362{
358 struct ep93xx_ac97_info *info; 363 struct ep93xx_ac97_info *info;
@@ -390,7 +395,8 @@ static int ep93xx_ac97_probe(struct platform_device *pdev)
390 ep93xx_ac97_info = info; 395 ep93xx_ac97_info = info;
391 platform_set_drvdata(pdev, info); 396 platform_set_drvdata(pdev, info);
392 397
393 ret = snd_soc_register_dai(&pdev->dev, &ep93xx_ac97_dai); 398 ret = snd_soc_register_component(&pdev->dev, &ep93xx_ac97_component,
399 &ep93xx_ac97_dai, 1);
394 if (ret) 400 if (ret)
395 goto fail; 401 goto fail;
396 402
@@ -407,7 +413,7 @@ static int ep93xx_ac97_remove(struct platform_device *pdev)
407{ 413{
408 struct ep93xx_ac97_info *info = platform_get_drvdata(pdev); 414 struct ep93xx_ac97_info *info = platform_get_drvdata(pdev);
409 415
410 snd_soc_unregister_dai(&pdev->dev); 416 snd_soc_unregister_component(&pdev->dev);
411 417
412 /* disable the AC97 controller */ 418 /* disable the AC97 controller */
413 ep93xx_ac97_write_reg(info, AC97GCR, 0); 419 ep93xx_ac97_write_reg(info, AC97GCR, 0);
diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c
index 323ed69b7975..5c1102e9e159 100644
--- a/sound/soc/cirrus/ep93xx-i2s.c
+++ b/sound/soc/cirrus/ep93xx-i2s.c
@@ -30,8 +30,6 @@
30#include <mach/ep93xx-regs.h> 30#include <mach/ep93xx-regs.h>
31#include <linux/platform_data/dma-ep93xx.h> 31#include <linux/platform_data/dma-ep93xx.h>
32 32
33#include "ep93xx-pcm.h"
34
35#define EP93XX_I2S_TXCLKCFG 0x00 33#define EP93XX_I2S_TXCLKCFG 0x00
36#define EP93XX_I2S_RXCLKCFG 0x04 34#define EP93XX_I2S_RXCLKCFG 0x04
37#define EP93XX_I2S_GLCTRL 0x0C 35#define EP93XX_I2S_GLCTRL 0x0C
@@ -62,18 +60,20 @@ struct ep93xx_i2s_info {
62 struct clk *mclk; 60 struct clk *mclk;
63 struct clk *sclk; 61 struct clk *sclk;
64 struct clk *lrclk; 62 struct clk *lrclk;
65 struct ep93xx_pcm_dma_params *dma_params; 63 struct ep93xx_dma_data *dma_data;
66 void __iomem *regs; 64 void __iomem *regs;
67}; 65};
68 66
69struct ep93xx_pcm_dma_params ep93xx_i2s_dma_params[] = { 67struct ep93xx_dma_data ep93xx_i2s_dma_data[] = {
70 [SNDRV_PCM_STREAM_PLAYBACK] = { 68 [SNDRV_PCM_STREAM_PLAYBACK] = {
71 .name = "i2s-pcm-out", 69 .name = "i2s-pcm-out",
72 .dma_port = EP93XX_DMA_I2S1, 70 .port = EP93XX_DMA_I2S1,
71 .direction = DMA_MEM_TO_DEV,
73 }, 72 },
74 [SNDRV_PCM_STREAM_CAPTURE] = { 73 [SNDRV_PCM_STREAM_CAPTURE] = {
75 .name = "i2s-pcm-in", 74 .name = "i2s-pcm-in",
76 .dma_port = EP93XX_DMA_I2S1, 75 .port = EP93XX_DMA_I2S1,
76 .direction = DMA_DEV_TO_MEM,
77 }, 77 },
78}; 78};
79 79
@@ -147,7 +147,7 @@ static int ep93xx_i2s_startup(struct snd_pcm_substream *substream,
147 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 147 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
148 148
149 snd_soc_dai_set_dma_data(cpu_dai, substream, 149 snd_soc_dai_set_dma_data(cpu_dai, substream,
150 &info->dma_params[substream->stream]); 150 &info->dma_data[substream->stream]);
151 return 0; 151 return 0;
152} 152}
153 153
@@ -366,6 +366,10 @@ static struct snd_soc_dai_driver ep93xx_i2s_dai = {
366 .ops = &ep93xx_i2s_dai_ops, 366 .ops = &ep93xx_i2s_dai_ops,
367}; 367};
368 368
369static const struct snd_soc_component_driver ep93xx_i2s_component = {
370 .name = "ep93xx-i2s",
371};
372
369static int ep93xx_i2s_probe(struct platform_device *pdev) 373static int ep93xx_i2s_probe(struct platform_device *pdev)
370{ 374{
371 struct ep93xx_i2s_info *info; 375 struct ep93xx_i2s_info *info;
@@ -403,9 +407,10 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
403 } 407 }
404 408
405 dev_set_drvdata(&pdev->dev, info); 409 dev_set_drvdata(&pdev->dev, info);
406 info->dma_params = ep93xx_i2s_dma_params; 410 info->dma_data = ep93xx_i2s_dma_data;
407 411
408 err = snd_soc_register_dai(&pdev->dev, &ep93xx_i2s_dai); 412 err = snd_soc_register_component(&pdev->dev, &ep93xx_i2s_component,
413 &ep93xx_i2s_dai, 1);
409 if (err) 414 if (err)
410 goto fail_put_lrclk; 415 goto fail_put_lrclk;
411 416
@@ -426,7 +431,7 @@ static int ep93xx_i2s_remove(struct platform_device *pdev)
426{ 431{
427 struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev); 432 struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev);
428 433
429 snd_soc_unregister_dai(&pdev->dev); 434 snd_soc_unregister_component(&pdev->dev);
430 dev_set_drvdata(&pdev->dev, NULL); 435 dev_set_drvdata(&pdev->dev, NULL);
431 clk_put(info->lrclk); 436 clk_put(info->lrclk);
432 clk_put(info->sclk); 437 clk_put(info->sclk);
diff --git a/sound/soc/cirrus/ep93xx-pcm.c b/sound/soc/cirrus/ep93xx-pcm.c
index 72eb7a49e16a..488032690378 100644
--- a/sound/soc/cirrus/ep93xx-pcm.c
+++ b/sound/soc/cirrus/ep93xx-pcm.c
@@ -29,8 +29,6 @@
29#include <mach/hardware.h> 29#include <mach/hardware.h>
30#include <mach/ep93xx-regs.h> 30#include <mach/ep93xx-regs.h>
31 31
32#include "ep93xx-pcm.h"
33
34static const struct snd_pcm_hardware ep93xx_pcm_hardware = { 32static const struct snd_pcm_hardware ep93xx_pcm_hardware = {
35 .info = (SNDRV_PCM_INFO_MMAP | 33 .info = (SNDRV_PCM_INFO_MMAP |
36 SNDRV_PCM_INFO_MMAP_VALID | 34 SNDRV_PCM_INFO_MMAP_VALID |
@@ -68,40 +66,12 @@ static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param)
68static int ep93xx_pcm_open(struct snd_pcm_substream *substream) 66static int ep93xx_pcm_open(struct snd_pcm_substream *substream)
69{ 67{
70 struct snd_soc_pcm_runtime *rtd = substream->private_data; 68 struct snd_soc_pcm_runtime *rtd = substream->private_data;
71 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
72 struct ep93xx_pcm_dma_params *dma_params;
73 struct ep93xx_dma_data *dma_data;
74 int ret;
75 69
76 snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware); 70 snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware);
77 71
78 dma_data = kmalloc(sizeof(*dma_data), GFP_KERNEL); 72 return snd_dmaengine_pcm_open_request_chan(substream,
79 if (!dma_data) 73 ep93xx_pcm_dma_filter,
80 return -ENOMEM; 74 snd_soc_dai_get_dma_data(rtd->cpu_dai, substream));
81
82 dma_params = snd_soc_dai_get_dma_data(cpu_dai, substream);
83 dma_data->port = dma_params->dma_port;
84 dma_data->name = dma_params->name;
85 dma_data->direction = snd_pcm_substream_to_dma_direction(substream);
86
87 ret = snd_dmaengine_pcm_open(substream, ep93xx_pcm_dma_filter, dma_data);
88 if (ret) {
89 kfree(dma_data);
90 return ret;
91 }
92
93 snd_dmaengine_pcm_set_data(substream, dma_data);
94
95 return 0;
96}
97
98static int ep93xx_pcm_close(struct snd_pcm_substream *substream)
99{
100 struct dma_data *dma_data = snd_dmaengine_pcm_get_data(substream);
101
102 snd_dmaengine_pcm_close(substream);
103 kfree(dma_data);
104 return 0;
105} 75}
106 76
107static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream, 77static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream,
@@ -131,7 +101,7 @@ static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream,
131 101
132static struct snd_pcm_ops ep93xx_pcm_ops = { 102static struct snd_pcm_ops ep93xx_pcm_ops = {
133 .open = ep93xx_pcm_open, 103 .open = ep93xx_pcm_open,
134 .close = ep93xx_pcm_close, 104 .close = snd_dmaengine_pcm_close_release_chan,
135 .ioctl = snd_pcm_lib_ioctl, 105 .ioctl = snd_pcm_lib_ioctl,
136 .hw_params = ep93xx_pcm_hw_params, 106 .hw_params = ep93xx_pcm_hw_params,
137 .hw_free = ep93xx_pcm_hw_free, 107 .hw_free = ep93xx_pcm_hw_free,
diff --git a/sound/soc/cirrus/ep93xx-pcm.h b/sound/soc/cirrus/ep93xx-pcm.h
deleted file mode 100644
index 111e1121ecb8..000000000000
--- a/sound/soc/cirrus/ep93xx-pcm.h
+++ /dev/null
@@ -1,20 +0,0 @@
1/*
2 * sound/soc/ep93xx/ep93xx-pcm.h - EP93xx ALSA PCM interface
3 *
4 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
5 * Copyright (C) 2006 Applied Data Systems
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef _EP93XX_SND_SOC_PCM_H
13#define _EP93XX_SND_SOC_PCM_H
14
15struct ep93xx_pcm_dma_params {
16 char *name;
17 int dma_port;
18};
19
20#endif /* _EP93XX_SND_SOC_PCM_H */
diff --git a/sound/soc/cirrus/simone.c b/sound/soc/cirrus/simone.c
index a397bb0d8179..4d094d00c34a 100644
--- a/sound/soc/cirrus/simone.c
+++ b/sound/soc/cirrus/simone.c
@@ -21,8 +21,6 @@
21#include <asm/mach-types.h> 21#include <asm/mach-types.h>
22#include <mach/hardware.h> 22#include <mach/hardware.h>
23 23
24#include "ep93xx-pcm.h"
25
26static struct snd_soc_dai_link simone_dai = { 24static struct snd_soc_dai_link simone_dai = {
27 .name = "AC97", 25 .name = "AC97",
28 .stream_name = "AC97 HiFi", 26 .stream_name = "AC97 HiFi",
diff --git a/sound/soc/cirrus/snappercl15.c b/sound/soc/cirrus/snappercl15.c
index 9d77fe28dfcc..69041074f2c1 100644
--- a/sound/soc/cirrus/snappercl15.c
+++ b/sound/soc/cirrus/snappercl15.c
@@ -21,7 +21,6 @@
21#include <mach/hardware.h> 21#include <mach/hardware.h>
22 22
23#include "../codecs/tlv320aic23.h" 23#include "../codecs/tlv320aic23.h"
24#include "ep93xx-pcm.h"
25 24
26#define CODEC_CLOCK 5644800 25#define CODEC_CLOCK 5644800
27 26
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 45b72561c615..2f45f00e31b0 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -26,6 +26,7 @@ config SND_SOC_ALL_CODECS
26 select SND_SOC_AK4641 if I2C 26 select SND_SOC_AK4641 if I2C
27 select SND_SOC_AK4642 if I2C 27 select SND_SOC_AK4642 if I2C
28 select SND_SOC_AK4671 if I2C 28 select SND_SOC_AK4671 if I2C
29 select SND_SOC_AK5386
29 select SND_SOC_ALC5623 if I2C 30 select SND_SOC_ALC5623 if I2C
30 select SND_SOC_ALC5632 if I2C 31 select SND_SOC_ALC5632 if I2C
31 select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC 32 select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
@@ -63,6 +64,7 @@ config SND_SOC_ALL_CODECS
63 select SND_SOC_STA32X if I2C 64 select SND_SOC_STA32X if I2C
64 select SND_SOC_STA529 if I2C 65 select SND_SOC_STA529 if I2C
65 select SND_SOC_STAC9766 if SND_SOC_AC97_BUS 66 select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
67 select SND_SOC_TAS5086 if I2C
66 select SND_SOC_TLV320AIC23 if I2C 68 select SND_SOC_TLV320AIC23 if I2C
67 select SND_SOC_TLV320AIC26 if SPI_MASTER 69 select SND_SOC_TLV320AIC26 if SPI_MASTER
68 select SND_SOC_TLV320AIC32X4 if I2C 70 select SND_SOC_TLV320AIC32X4 if I2C
@@ -203,6 +205,9 @@ config SND_SOC_AK4642
203config SND_SOC_AK4671 205config SND_SOC_AK4671
204 tristate 206 tristate
205 207
208config SND_SOC_AK5386
209 tristate
210
206config SND_SOC_ALC5623 211config SND_SOC_ALC5623
207 tristate 212 tristate
208config SND_SOC_ALC5632 213config SND_SOC_ALC5632
@@ -320,11 +325,14 @@ config SND_SOC_STA529
320config SND_SOC_STAC9766 325config SND_SOC_STAC9766
321 tristate 326 tristate
322 327
328config SND_SOC_TAS5086
329 tristate
330
323config SND_SOC_TLV320AIC23 331config SND_SOC_TLV320AIC23
324 tristate 332 tristate
325 333
326config SND_SOC_TLV320AIC26 334config SND_SOC_TLV320AIC26
327 tristate "TI TLV320AIC26 Codec support" if SND_SOC_OF_SIMPLE 335 tristate
328 depends on SPI 336 depends on SPI
329 337
330config SND_SOC_TLV320AIC32X4 338config SND_SOC_TLV320AIC32X4
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 6a3b3c3b8b41..b9e41c9a1f4c 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -14,6 +14,7 @@ snd-soc-ak4535-objs := ak4535.o
14snd-soc-ak4641-objs := ak4641.o 14snd-soc-ak4641-objs := ak4641.o
15snd-soc-ak4642-objs := ak4642.o 15snd-soc-ak4642-objs := ak4642.o
16snd-soc-ak4671-objs := ak4671.o 16snd-soc-ak4671-objs := ak4671.o
17snd-soc-ak5386-objs := ak5386.o
17snd-soc-arizona-objs := arizona.o 18snd-soc-arizona-objs := arizona.o
18snd-soc-cq93vc-objs := cq93vc.o 19snd-soc-cq93vc-objs := cq93vc.o
19snd-soc-cs42l51-objs := cs42l51.o 20snd-soc-cs42l51-objs := cs42l51.o
@@ -55,6 +56,7 @@ snd-soc-ssm2602-objs := ssm2602.o
55snd-soc-sta32x-objs := sta32x.o 56snd-soc-sta32x-objs := sta32x.o
56snd-soc-sta529-objs := sta529.o 57snd-soc-sta529-objs := sta529.o
57snd-soc-stac9766-objs := stac9766.o 58snd-soc-stac9766-objs := stac9766.o
59snd-soc-tas5086-objs := tas5086.o
58snd-soc-tlv320aic23-objs := tlv320aic23.o 60snd-soc-tlv320aic23-objs := tlv320aic23.o
59snd-soc-tlv320aic26-objs := tlv320aic26.o 61snd-soc-tlv320aic26-objs := tlv320aic26.o
60snd-soc-tlv320aic3x-objs := tlv320aic3x.o 62snd-soc-tlv320aic3x-objs := tlv320aic3x.o
@@ -137,6 +139,7 @@ obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o
137obj-$(CONFIG_SND_SOC_AK4641) += snd-soc-ak4641.o 139obj-$(CONFIG_SND_SOC_AK4641) += snd-soc-ak4641.o
138obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o 140obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o
139obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o 141obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o
142obj-$(CONFIG_SND_SOC_AK5386) += snd-soc-ak5386.o
140obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o 143obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o
141obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o 144obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o
142obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o 145obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o
@@ -177,6 +180,7 @@ obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
177obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o 180obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o
178obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o 181obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o
179obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o 182obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
183obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o
180obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o 184obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
181obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o 185obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
182obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o 186obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c
index 068b3ae56a17..1aa10ddf3a61 100644
--- a/sound/soc/codecs/adau1373.c
+++ b/sound/soc/codecs/adau1373.c
@@ -133,6 +133,8 @@ struct adau1373 {
133#define ADAU1373_DAI_FORMAT_DSP 0x3 133#define ADAU1373_DAI_FORMAT_DSP 0x3
134 134
135#define ADAU1373_BCLKDIV_SOURCE BIT(5) 135#define ADAU1373_BCLKDIV_SOURCE BIT(5)
136#define ADAU1373_BCLKDIV_SR_MASK (0x07 << 2)
137#define ADAU1373_BCLKDIV_BCLK_MASK 0x03
136#define ADAU1373_BCLKDIV_32 0x03 138#define ADAU1373_BCLKDIV_32 0x03
137#define ADAU1373_BCLKDIV_64 0x02 139#define ADAU1373_BCLKDIV_64 0x02
138#define ADAU1373_BCLKDIV_128 0x01 140#define ADAU1373_BCLKDIV_128 0x01
@@ -937,7 +939,8 @@ static int adau1373_hw_params(struct snd_pcm_substream *substream,
937 adau1373_dai->enable_src = (div != 0); 939 adau1373_dai->enable_src = (div != 0);
938 940
939 snd_soc_update_bits(codec, ADAU1373_BCLKDIV(dai->id), 941 snd_soc_update_bits(codec, ADAU1373_BCLKDIV(dai->id),
940 ~ADAU1373_BCLKDIV_SOURCE, (div << 2) | ADAU1373_BCLKDIV_64); 942 ADAU1373_BCLKDIV_SR_MASK | ADAU1373_BCLKDIV_BCLK_MASK,
943 (div << 2) | ADAU1373_BCLKDIV_64);
941 944
942 switch (params_format(params)) { 945 switch (params_format(params)) {
943 case SNDRV_PCM_FORMAT_S16_LE: 946 case SNDRV_PCM_FORMAT_S16_LE:
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index 6f6c335a5baa..c7cfdf957e4d 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -55,6 +55,7 @@ static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai,
55 unsigned int format) 55 unsigned int format)
56{ 56{
57 struct snd_soc_codec *codec = codec_dai->codec; 57 struct snd_soc_codec *codec = codec_dai->codec;
58 struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);
58 int val = 0; 59 int val = 0;
59 int ret; 60 int ret;
60 61
@@ -77,9 +78,9 @@ static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai,
77 if ((format & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) 78 if ((format & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS)
78 return -EINVAL; 79 return -EINVAL;
79 80
80 ret = snd_soc_update_bits(codec, AK4104_REG_CONTROL1, 81 ret = regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1,
81 AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1, 82 AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1,
82 val); 83 val);
83 if (ret < 0) 84 if (ret < 0)
84 return ret; 85 return ret;
85 86
@@ -91,11 +92,12 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
91 struct snd_soc_dai *dai) 92 struct snd_soc_dai *dai)
92{ 93{
93 struct snd_soc_codec *codec = dai->codec; 94 struct snd_soc_codec *codec = dai->codec;
94 int val = 0; 95 struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);
96 int ret, val = 0;
95 97
96 /* set the IEC958 bits: consumer mode, no copyright bit */ 98 /* set the IEC958 bits: consumer mode, no copyright bit */
97 val |= IEC958_AES0_CON_NOT_COPYRIGHT; 99 val |= IEC958_AES0_CON_NOT_COPYRIGHT;
98 snd_soc_write(codec, AK4104_REG_CHN_STATUS(0), val); 100 regmap_write(ak4104->regmap, AK4104_REG_CHN_STATUS(0), val);
99 101
100 val = 0; 102 val = 0;
101 103
@@ -132,11 +134,33 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
132 return -EINVAL; 134 return -EINVAL;
133 } 135 }
134 136
135 return snd_soc_write(codec, AK4104_REG_CHN_STATUS(3), val); 137 ret = regmap_write(ak4104->regmap, AK4104_REG_CHN_STATUS(3), val);
138 if (ret < 0)
139 return ret;
140
141 /* enable transmitter */
142 ret = regmap_update_bits(ak4104->regmap, AK4104_REG_TX,
143 AK4104_TX_TXE, AK4104_TX_TXE);
144 if (ret < 0)
145 return ret;
146
147 return 0;
148}
149
150static int ak4104_hw_free(struct snd_pcm_substream *substream,
151 struct snd_soc_dai *dai)
152{
153 struct snd_soc_codec *codec = dai->codec;
154 struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);
155
156 /* disable transmitter */
157 return regmap_update_bits(ak4104->regmap, AK4104_REG_TX,
158 AK4104_TX_TXE, 0);
136} 159}
137 160
138static const struct snd_soc_dai_ops ak4101_dai_ops = { 161static const struct snd_soc_dai_ops ak4101_dai_ops = {
139 .hw_params = ak4104_hw_params, 162 .hw_params = ak4104_hw_params,
163 .hw_free = ak4104_hw_free,
140 .set_fmt = ak4104_set_dai_fmt, 164 .set_fmt = ak4104_set_dai_fmt,
141}; 165};
142 166
@@ -160,20 +184,17 @@ static int ak4104_probe(struct snd_soc_codec *codec)
160 int ret; 184 int ret;
161 185
162 codec->control_data = ak4104->regmap; 186 codec->control_data = ak4104->regmap;
163 ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
164 if (ret != 0)
165 return ret;
166 187
167 /* set power-up and non-reset bits */ 188 /* set power-up and non-reset bits */
168 ret = snd_soc_update_bits(codec, AK4104_REG_CONTROL1, 189 ret = regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1,
169 AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, 190 AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN,
170 AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN); 191 AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN);
171 if (ret < 0) 192 if (ret < 0)
172 return ret; 193 return ret;
173 194
174 /* enable transmitter */ 195 /* enable transmitter */
175 ret = snd_soc_update_bits(codec, AK4104_REG_TX, 196 ret = regmap_update_bits(ak4104->regmap, AK4104_REG_TX,
176 AK4104_TX_TXE, AK4104_TX_TXE); 197 AK4104_TX_TXE, AK4104_TX_TXE);
177 if (ret < 0) 198 if (ret < 0)
178 return ret; 199 return ret;
179 200
@@ -182,8 +203,10 @@ static int ak4104_probe(struct snd_soc_codec *codec)
182 203
183static int ak4104_remove(struct snd_soc_codec *codec) 204static int ak4104_remove(struct snd_soc_codec *codec)
184{ 205{
185 snd_soc_update_bits(codec, AK4104_REG_CONTROL1, 206 struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);
186 AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, 0); 207
208 regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1,
209 AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, 0);
187 210
188 return 0; 211 return 0;
189} 212}
diff --git a/sound/soc/codecs/ak5386.c b/sound/soc/codecs/ak5386.c
new file mode 100644
index 000000000000..1f303983ae02
--- /dev/null
+++ b/sound/soc/codecs/ak5386.c
@@ -0,0 +1,152 @@
1/*
2 * ALSA SoC driver for
3 * Asahi Kasei AK5386 Single-ended 24-Bit 192kHz delta-sigma ADC
4 *
5 * (c) 2013 Daniel Mack <zonque@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/module.h>
13#include <linux/slab.h>
14#include <linux/of.h>
15#include <linux/of_gpio.h>
16#include <linux/of_device.h>
17#include <sound/soc.h>
18#include <sound/pcm.h>
19#include <sound/initval.h>
20
21struct ak5386_priv {
22 int reset_gpio;
23};
24
25static struct snd_soc_codec_driver soc_codec_ak5386;
26
27static int ak5386_set_dai_fmt(struct snd_soc_dai *codec_dai,
28 unsigned int format)
29{
30 struct snd_soc_codec *codec = codec_dai->codec;
31
32 format &= SND_SOC_DAIFMT_FORMAT_MASK;
33 if (format != SND_SOC_DAIFMT_LEFT_J &&
34 format != SND_SOC_DAIFMT_I2S) {
35 dev_err(codec->dev, "Invalid DAI format\n");
36 return -EINVAL;
37 }
38
39 return 0;
40}
41
42static int ak5386_hw_params(struct snd_pcm_substream *substream,
43 struct snd_pcm_hw_params *params,
44 struct snd_soc_dai *dai)
45{
46 struct snd_soc_codec *codec = dai->codec;
47 struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
48
49 /*
50 * From the datasheet:
51 *
52 * All external clocks (MCLK, SCLK and LRCK) must be present unless
53 * PDN pin = “L”. If these clocks are not provided, the AK5386 may
54 * draw excess current due to its use of internal dynamically
55 * refreshed logic. If the external clocks are not present, place
56 * the AK5386 in power-down mode (PDN pin = “L”).
57 */
58
59 if (gpio_is_valid(priv->reset_gpio))
60 gpio_set_value(priv->reset_gpio, 1);
61
62 return 0;
63}
64
65static int ak5386_hw_free(struct snd_pcm_substream *substream,
66 struct snd_soc_dai *dai)
67{
68 struct snd_soc_codec *codec = dai->codec;
69 struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
70
71 if (gpio_is_valid(priv->reset_gpio))
72 gpio_set_value(priv->reset_gpio, 0);
73
74 return 0;
75}
76
77static const struct snd_soc_dai_ops ak5386_dai_ops = {
78 .set_fmt = ak5386_set_dai_fmt,
79 .hw_params = ak5386_hw_params,
80 .hw_free = ak5386_hw_free,
81};
82
83static struct snd_soc_dai_driver ak5386_dai = {
84 .name = "ak5386-hifi",
85 .capture = {
86 .stream_name = "Capture",
87 .channels_min = 1,
88 .channels_max = 2,
89 .rates = SNDRV_PCM_RATE_8000_192000,
90 .formats = SNDRV_PCM_FMTBIT_S8 |
91 SNDRV_PCM_FMTBIT_S16_LE |
92 SNDRV_PCM_FMTBIT_S24_LE |
93 SNDRV_PCM_FMTBIT_S24_3LE,
94 },
95 .ops = &ak5386_dai_ops,
96};
97
98#ifdef CONFIG_OF
99static const struct of_device_id ak5386_dt_ids[] = {
100 { .compatible = "asahi-kasei,ak5386", },
101 { }
102};
103MODULE_DEVICE_TABLE(of, ak5386_dt_ids);
104#endif
105
106static int ak5386_probe(struct platform_device *pdev)
107{
108 struct device *dev = &pdev->dev;
109 struct ak5386_priv *priv;
110
111 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
112 if (!priv)
113 return -ENOMEM;
114
115 priv->reset_gpio = -EINVAL;
116 dev_set_drvdata(dev, priv);
117
118 if (of_match_device(of_match_ptr(ak5386_dt_ids), dev))
119 priv->reset_gpio = of_get_named_gpio(dev->of_node,
120 "reset-gpio", 0);
121
122 if (gpio_is_valid(priv->reset_gpio))
123 if (devm_gpio_request_one(dev, priv->reset_gpio,
124 GPIOF_OUT_INIT_LOW,
125 "AK5386 Reset"))
126 priv->reset_gpio = -EINVAL;
127
128 return snd_soc_register_codec(dev, &soc_codec_ak5386,
129 &ak5386_dai, 1);
130}
131
132static int ak5386_remove(struct platform_device *pdev)
133{
134 snd_soc_unregister_codec(&pdev->dev);
135 return 0;
136}
137
138static struct platform_driver ak5386_driver = {
139 .probe = ak5386_probe,
140 .remove = ak5386_remove,
141 .driver = {
142 .name = "ak5386",
143 .owner = THIS_MODULE,
144 .of_match_table = of_match_ptr(ak5386_dt_ids),
145 },
146};
147
148module_platform_driver(ak5386_driver);
149
150MODULE_DESCRIPTION("ASoC driver for AK5386 ADC");
151MODULE_AUTHOR("Daniel Mack <zonque@gmail.com>");
152MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
index e7d34711412c..389f23253831 100644
--- a/sound/soc/codecs/arizona.c
+++ b/sound/soc/codecs/arizona.c
@@ -10,6 +10,7 @@
10 * published by the Free Software Foundation. 10 * published by the Free Software Foundation.
11 */ 11 */
12 12
13#include <linux/delay.h>
13#include <linux/gcd.h> 14#include <linux/gcd.h>
14#include <linux/module.h> 15#include <linux/module.h>
15#include <linux/pm_runtime.h> 16#include <linux/pm_runtime.h>
@@ -65,6 +66,163 @@
65#define arizona_aif_dbg(_dai, fmt, ...) \ 66#define arizona_aif_dbg(_dai, fmt, ...) \
66 dev_dbg(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__) 67 dev_dbg(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
67 68
69static int arizona_spk_ev(struct snd_soc_dapm_widget *w,
70 struct snd_kcontrol *kcontrol,
71 int event)
72{
73 struct snd_soc_codec *codec = w->codec;
74 struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
75 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
76 bool manual_ena = false;
77 int val;
78
79 switch (arizona->type) {
80 case WM5102:
81 switch (arizona->rev) {
82 case 0:
83 break;
84 default:
85 manual_ena = true;
86 break;
87 }
88 default:
89 break;
90 }
91
92 switch (event) {
93 case SND_SOC_DAPM_PRE_PMU:
94 if (!priv->spk_ena && manual_ena) {
95 snd_soc_write(codec, 0x4f5, 0x25a);
96 priv->spk_ena_pending = true;
97 }
98 break;
99 case SND_SOC_DAPM_POST_PMU:
100 val = snd_soc_read(codec, ARIZONA_INTERRUPT_RAW_STATUS_3);
101 if (val & ARIZONA_SPK_SHUTDOWN_STS) {
102 dev_crit(arizona->dev,
103 "Speaker not enabled due to temperature\n");
104 return -EBUSY;
105 }
106
107 snd_soc_update_bits(codec, ARIZONA_OUTPUT_ENABLES_1,
108 1 << w->shift, 1 << w->shift);
109
110 if (priv->spk_ena_pending) {
111 msleep(75);
112 snd_soc_write(codec, 0x4f5, 0xda);
113 priv->spk_ena_pending = false;
114 priv->spk_ena++;
115 }
116 break;
117 case SND_SOC_DAPM_PRE_PMD:
118 if (manual_ena) {
119 priv->spk_ena--;
120 if (!priv->spk_ena)
121 snd_soc_write(codec, 0x4f5, 0x25a);
122 }
123
124 snd_soc_update_bits(codec, ARIZONA_OUTPUT_ENABLES_1,
125 1 << w->shift, 0);
126 break;
127 case SND_SOC_DAPM_POST_PMD:
128 if (manual_ena) {
129 if (!priv->spk_ena)
130 snd_soc_write(codec, 0x4f5, 0x0da);
131 }
132 break;
133 }
134
135 return 0;
136}
137
138static irqreturn_t arizona_thermal_warn(int irq, void *data)
139{
140 struct arizona *arizona = data;
141 unsigned int val;
142 int ret;
143
144 ret = regmap_read(arizona->regmap, ARIZONA_INTERRUPT_RAW_STATUS_3,
145 &val);
146 if (ret != 0) {
147 dev_err(arizona->dev, "Failed to read thermal status: %d\n",
148 ret);
149 } else if (val & ARIZONA_SPK_SHUTDOWN_WARN_STS) {
150 dev_crit(arizona->dev, "Thermal warning\n");
151 }
152
153 return IRQ_HANDLED;
154}
155
156static irqreturn_t arizona_thermal_shutdown(int irq, void *data)
157{
158 struct arizona *arizona = data;
159 unsigned int val;
160 int ret;
161
162 ret = regmap_read(arizona->regmap, ARIZONA_INTERRUPT_RAW_STATUS_3,
163 &val);
164 if (ret != 0) {
165 dev_err(arizona->dev, "Failed to read thermal status: %d\n",
166 ret);
167 } else if (val & ARIZONA_SPK_SHUTDOWN_STS) {
168 dev_crit(arizona->dev, "Thermal shutdown\n");
169 ret = regmap_update_bits(arizona->regmap,
170 ARIZONA_OUTPUT_ENABLES_1,
171 ARIZONA_OUT4L_ENA |
172 ARIZONA_OUT4R_ENA, 0);
173 if (ret != 0)
174 dev_crit(arizona->dev,
175 "Failed to disable speaker outputs: %d\n",
176 ret);
177 }
178
179 return IRQ_HANDLED;
180}
181
182static const struct snd_soc_dapm_widget arizona_spkl =
183 SND_SOC_DAPM_PGA_E("OUT4L", SND_SOC_NOPM,
184 ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_spk_ev,
185 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU);
186
187static const struct snd_soc_dapm_widget arizona_spkr =
188 SND_SOC_DAPM_PGA_E("OUT4R", SND_SOC_NOPM,
189 ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_spk_ev,
190 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU);
191
192int arizona_init_spk(struct snd_soc_codec *codec)
193{
194 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
195 struct arizona *arizona = priv->arizona;
196 int ret;
197
198 ret = snd_soc_dapm_new_controls(&codec->dapm, &arizona_spkl, 1);
199 if (ret != 0)
200 return ret;
201
202 ret = snd_soc_dapm_new_controls(&codec->dapm, &arizona_spkr, 1);
203 if (ret != 0)
204 return ret;
205
206 ret = arizona_request_irq(arizona, ARIZONA_IRQ_SPK_SHUTDOWN_WARN,
207 "Thermal warning", arizona_thermal_warn,
208 arizona);
209 if (ret != 0)
210 dev_err(arizona->dev,
211 "Failed to get thermal warning IRQ: %d\n",
212 ret);
213
214 ret = arizona_request_irq(arizona, ARIZONA_IRQ_SPK_SHUTDOWN,
215 "Thermal shutdown", arizona_thermal_shutdown,
216 arizona);
217 if (ret != 0)
218 dev_err(arizona->dev,
219 "Failed to get thermal shutdown IRQ: %d\n",
220 ret);
221
222 return 0;
223}
224EXPORT_SYMBOL_GPL(arizona_init_spk);
225
68const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = { 226const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = {
69 "None", 227 "None",
70 "Tone Generator 1", 228 "Tone Generator 1",
@@ -274,6 +432,33 @@ EXPORT_SYMBOL_GPL(arizona_mixer_values);
274const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0); 432const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0);
275EXPORT_SYMBOL_GPL(arizona_mixer_tlv); 433EXPORT_SYMBOL_GPL(arizona_mixer_tlv);
276 434
435const char *arizona_rate_text[ARIZONA_RATE_ENUM_SIZE] = {
436 "SYNCCLK rate", "8kHz", "16kHz", "ASYNCCLK rate",
437};
438EXPORT_SYMBOL_GPL(arizona_rate_text);
439
440const int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE] = {
441 0, 1, 2, 8,
442};
443EXPORT_SYMBOL_GPL(arizona_rate_val);
444
445
446const struct soc_enum arizona_isrc_fsl[] = {
447 SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_1_CTRL_2,
448 ARIZONA_ISRC1_FSL_SHIFT, 0xf,
449 ARIZONA_RATE_ENUM_SIZE,
450 arizona_rate_text, arizona_rate_val),
451 SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_2_CTRL_2,
452 ARIZONA_ISRC2_FSL_SHIFT, 0xf,
453 ARIZONA_RATE_ENUM_SIZE,
454 arizona_rate_text, arizona_rate_val),
455 SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_3_CTRL_2,
456 ARIZONA_ISRC3_FSL_SHIFT, 0xf,
457 ARIZONA_RATE_ENUM_SIZE,
458 arizona_rate_text, arizona_rate_val),
459};
460EXPORT_SYMBOL_GPL(arizona_isrc_fsl);
461
277static const char *arizona_vol_ramp_text[] = { 462static const char *arizona_vol_ramp_text[] = {
278 "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB", 463 "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB",
279 "15ms/6dB", "30ms/6dB", 464 "15ms/6dB", "30ms/6dB",
@@ -332,9 +517,27 @@ const struct soc_enum arizona_ng_hold =
332 4, arizona_ng_hold_text); 517 4, arizona_ng_hold_text);
333EXPORT_SYMBOL_GPL(arizona_ng_hold); 518EXPORT_SYMBOL_GPL(arizona_ng_hold);
334 519
520static void arizona_in_set_vu(struct snd_soc_codec *codec, int ena)
521{
522 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
523 unsigned int val;
524 int i;
525
526 if (ena)
527 val = ARIZONA_IN_VU;
528 else
529 val = 0;
530
531 for (i = 0; i < priv->num_inputs; i++)
532 snd_soc_update_bits(codec,
533 ARIZONA_ADC_DIGITAL_VOLUME_1L + (i * 4),
534 ARIZONA_IN_VU, val);
535}
536
335int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, 537int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
336 int event) 538 int event)
337{ 539{
540 struct arizona_priv *priv = snd_soc_codec_get_drvdata(w->codec);
338 unsigned int reg; 541 unsigned int reg;
339 542
340 if (w->shift % 2) 543 if (w->shift % 2)
@@ -343,13 +546,29 @@ int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
343 reg = ARIZONA_ADC_DIGITAL_VOLUME_1R + ((w->shift / 2) * 8); 546 reg = ARIZONA_ADC_DIGITAL_VOLUME_1R + ((w->shift / 2) * 8);
344 547
345 switch (event) { 548 switch (event) {
549 case SND_SOC_DAPM_PRE_PMU:
550 priv->in_pending++;
551 break;
346 case SND_SOC_DAPM_POST_PMU: 552 case SND_SOC_DAPM_POST_PMU:
347 snd_soc_update_bits(w->codec, reg, ARIZONA_IN1L_MUTE, 0); 553 snd_soc_update_bits(w->codec, reg, ARIZONA_IN1L_MUTE, 0);
554
555 /* If this is the last input pending then allow VU */
556 priv->in_pending--;
557 if (priv->in_pending == 0) {
558 msleep(1);
559 arizona_in_set_vu(w->codec, 1);
560 }
348 break; 561 break;
349 case SND_SOC_DAPM_PRE_PMD: 562 case SND_SOC_DAPM_PRE_PMD:
350 snd_soc_update_bits(w->codec, reg, ARIZONA_IN1L_MUTE, 563 snd_soc_update_bits(w->codec, reg,
351 ARIZONA_IN1L_MUTE); 564 ARIZONA_IN1L_MUTE | ARIZONA_IN_VU,
565 ARIZONA_IN1L_MUTE | ARIZONA_IN_VU);
352 break; 566 break;
567 case SND_SOC_DAPM_POST_PMD:
568 /* Disable volume updates if no inputs are enabled */
569 reg = snd_soc_read(w->codec, ARIZONA_INPUT_ENABLES);
570 if (reg == 0)
571 arizona_in_set_vu(w->codec, 0);
353 } 572 }
354 573
355 return 0; 574 return 0;
@@ -360,6 +579,24 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w,
360 struct snd_kcontrol *kcontrol, 579 struct snd_kcontrol *kcontrol,
361 int event) 580 int event)
362{ 581{
582 switch (event) {
583 case SND_SOC_DAPM_POST_PMU:
584 switch (w->shift) {
585 case ARIZONA_OUT1L_ENA_SHIFT:
586 case ARIZONA_OUT1R_ENA_SHIFT:
587 case ARIZONA_OUT2L_ENA_SHIFT:
588 case ARIZONA_OUT2R_ENA_SHIFT:
589 case ARIZONA_OUT3L_ENA_SHIFT:
590 case ARIZONA_OUT3R_ENA_SHIFT:
591 msleep(17);
592 break;
593
594 default:
595 break;
596 }
597 break;
598 }
599
363 return 0; 600 return 0;
364} 601}
365EXPORT_SYMBOL_GPL(arizona_out_ev); 602EXPORT_SYMBOL_GPL(arizona_out_ev);
@@ -502,27 +739,27 @@ int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
502 break; 739 break;
503 case 11289600: 740 case 11289600:
504 case 12288000: 741 case 12288000:
505 val |= 1 << ARIZONA_SYSCLK_FREQ_SHIFT; 742 val |= ARIZONA_CLK_12MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
506 break; 743 break;
507 case 22579200: 744 case 22579200:
508 case 24576000: 745 case 24576000:
509 val |= 2 << ARIZONA_SYSCLK_FREQ_SHIFT; 746 val |= ARIZONA_CLK_24MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
510 break; 747 break;
511 case 45158400: 748 case 45158400:
512 case 49152000: 749 case 49152000:
513 val |= 3 << ARIZONA_SYSCLK_FREQ_SHIFT; 750 val |= ARIZONA_CLK_49MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
514 break; 751 break;
515 case 67737600: 752 case 67737600:
516 case 73728000: 753 case 73728000:
517 val |= 4 << ARIZONA_SYSCLK_FREQ_SHIFT; 754 val |= ARIZONA_CLK_73MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
518 break; 755 break;
519 case 90316800: 756 case 90316800:
520 case 98304000: 757 case 98304000:
521 val |= 5 << ARIZONA_SYSCLK_FREQ_SHIFT; 758 val |= ARIZONA_CLK_98MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
522 break; 759 break;
523 case 135475200: 760 case 135475200:
524 case 147456000: 761 case 147456000:
525 val |= 6 << ARIZONA_SYSCLK_FREQ_SHIFT; 762 val |= ARIZONA_CLK_147MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
526 break; 763 break;
527 case 0: 764 case 0:
528 dev_dbg(arizona->dev, "%s cleared\n", name); 765 dev_dbg(arizona->dev, "%s cleared\n", name);
@@ -816,7 +1053,7 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
816 struct arizona *arizona = priv->arizona; 1053 struct arizona *arizona = priv->arizona;
817 int base = dai->driver->base; 1054 int base = dai->driver->base;
818 const int *rates; 1055 const int *rates;
819 int i, ret; 1056 int i, ret, val;
820 int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1]; 1057 int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1];
821 int bclk, lrclk, wl, frame, bclk_target; 1058 int bclk, lrclk, wl, frame, bclk_target;
822 1059
@@ -832,6 +1069,13 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
832 bclk_target *= chan_limit; 1069 bclk_target *= chan_limit;
833 } 1070 }
834 1071
1072 /* Force stereo for I2S mode */
1073 val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT);
1074 if (params_channels(params) == 1 && (val & ARIZONA_AIF1_FMT_MASK)) {
1075 arizona_aif_dbg(dai, "Forcing stereo mode\n");
1076 bclk_target *= 2;
1077 }
1078
835 for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) { 1079 for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
836 if (rates[i] >= bclk_target && 1080 if (rates[i] >= bclk_target &&
837 rates[i] % params_rate(params) == 0) { 1081 rates[i] % params_rate(params) == 0) {
@@ -988,6 +1232,16 @@ static struct {
988 { 1000000, 13500000, 0, 1 }, 1232 { 1000000, 13500000, 0, 1 },
989}; 1233};
990 1234
1235static struct {
1236 unsigned int min;
1237 unsigned int max;
1238 u16 gain;
1239} fll_gains[] = {
1240 { 0, 256000, 0 },
1241 { 256000, 1000000, 2 },
1242 { 1000000, 13500000, 4 },
1243};
1244
991struct arizona_fll_cfg { 1245struct arizona_fll_cfg {
992 int n; 1246 int n;
993 int theta; 1247 int theta;
@@ -995,6 +1249,7 @@ struct arizona_fll_cfg {
995 int refdiv; 1249 int refdiv;
996 int outdiv; 1250 int outdiv;
997 int fratio; 1251 int fratio;
1252 int gain;
998}; 1253};
999 1254
1000static int arizona_calc_fll(struct arizona_fll *fll, 1255static int arizona_calc_fll(struct arizona_fll *fll,
@@ -1054,6 +1309,18 @@ static int arizona_calc_fll(struct arizona_fll *fll,
1054 return -EINVAL; 1309 return -EINVAL;
1055 } 1310 }
1056 1311
1312 for (i = 0; i < ARRAY_SIZE(fll_gains); i++) {
1313 if (fll_gains[i].min <= Fref && Fref <= fll_gains[i].max) {
1314 cfg->gain = fll_gains[i].gain;
1315 break;
1316 }
1317 }
1318 if (i == ARRAY_SIZE(fll_gains)) {
1319 arizona_fll_err(fll, "Unable to find gain for Fref=%uHz\n",
1320 Fref);
1321 return -EINVAL;
1322 }
1323
1057 cfg->n = target / (ratio * Fref); 1324 cfg->n = target / (ratio * Fref);
1058 1325
1059 if (target % (ratio * Fref)) { 1326 if (target % (ratio * Fref)) {
@@ -1081,13 +1348,15 @@ static int arizona_calc_fll(struct arizona_fll *fll,
1081 cfg->n, cfg->theta, cfg->lambda); 1348 cfg->n, cfg->theta, cfg->lambda);
1082 arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n", 1349 arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n",
1083 cfg->fratio, cfg->fratio, cfg->outdiv, cfg->refdiv); 1350 cfg->fratio, cfg->fratio, cfg->outdiv, cfg->refdiv);
1351 arizona_fll_dbg(fll, "GAIN=%d\n", cfg->gain);
1084 1352
1085 return 0; 1353 return 0;
1086 1354
1087} 1355}
1088 1356
1089static void arizona_apply_fll(struct arizona *arizona, unsigned int base, 1357static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
1090 struct arizona_fll_cfg *cfg, int source) 1358 struct arizona_fll_cfg *cfg, int source,
1359 bool sync)
1091{ 1360{
1092 regmap_update_bits(arizona->regmap, base + 3, 1361 regmap_update_bits(arizona->regmap, base + 3,
1093 ARIZONA_FLL1_THETA_MASK, cfg->theta); 1362 ARIZONA_FLL1_THETA_MASK, cfg->theta);
@@ -1102,87 +1371,84 @@ static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
1102 cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT | 1371 cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT |
1103 source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT); 1372 source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT);
1104 1373
1374 if (sync)
1375 regmap_update_bits(arizona->regmap, base + 0x7,
1376 ARIZONA_FLL1_GAIN_MASK,
1377 cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
1378 else
1379 regmap_update_bits(arizona->regmap, base + 0x9,
1380 ARIZONA_FLL1_GAIN_MASK,
1381 cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
1382
1105 regmap_update_bits(arizona->regmap, base + 2, 1383 regmap_update_bits(arizona->regmap, base + 2,
1106 ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK, 1384 ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK,
1107 ARIZONA_FLL1_CTRL_UPD | cfg->n); 1385 ARIZONA_FLL1_CTRL_UPD | cfg->n);
1108} 1386}
1109 1387
1110int arizona_set_fll(struct arizona_fll *fll, int source, 1388static bool arizona_is_enabled_fll(struct arizona_fll *fll)
1111 unsigned int Fref, unsigned int Fout)
1112{ 1389{
1113 struct arizona *arizona = fll->arizona; 1390 struct arizona *arizona = fll->arizona;
1114 struct arizona_fll_cfg cfg, sync; 1391 unsigned int reg;
1115 unsigned int reg, val;
1116 int syncsrc;
1117 bool ena;
1118 int ret; 1392 int ret;
1119 1393
1120 if (fll->fref == Fref && fll->fout == Fout)
1121 return 0;
1122
1123 ret = regmap_read(arizona->regmap, fll->base + 1, &reg); 1394 ret = regmap_read(arizona->regmap, fll->base + 1, &reg);
1124 if (ret != 0) { 1395 if (ret != 0) {
1125 arizona_fll_err(fll, "Failed to read current state: %d\n", 1396 arizona_fll_err(fll, "Failed to read current state: %d\n",
1126 ret); 1397 ret);
1127 return ret; 1398 return ret;
1128 } 1399 }
1129 ena = reg & ARIZONA_FLL1_ENA;
1130 1400
1131 if (Fout) { 1401 return reg & ARIZONA_FLL1_ENA;
1132 /* Do we have a 32kHz reference? */ 1402}
1133 regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val);
1134 switch (val & ARIZONA_CLK_32K_SRC_MASK) {
1135 case ARIZONA_CLK_SRC_MCLK1:
1136 case ARIZONA_CLK_SRC_MCLK2:
1137 syncsrc = val & ARIZONA_CLK_32K_SRC_MASK;
1138 break;
1139 default:
1140 syncsrc = -1;
1141 }
1142 1403
1143 if (source == syncsrc) 1404static void arizona_enable_fll(struct arizona_fll *fll,
1144 syncsrc = -1; 1405 struct arizona_fll_cfg *ref,
1406 struct arizona_fll_cfg *sync)
1407{
1408 struct arizona *arizona = fll->arizona;
1409 int ret;
1145 1410
1146 if (syncsrc >= 0) { 1411 /*
1147 ret = arizona_calc_fll(fll, &sync, Fref, Fout); 1412 * If we have both REFCLK and SYNCCLK then enable both,
1148 if (ret != 0) 1413 * otherwise apply the SYNCCLK settings to REFCLK.
1149 return ret; 1414 */
1415 if (fll->ref_src >= 0 && fll->ref_src != fll->sync_src) {
1416 regmap_update_bits(arizona->regmap, fll->base + 5,
1417 ARIZONA_FLL1_OUTDIV_MASK,
1418 ref->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
1419
1420 arizona_apply_fll(arizona, fll->base, ref, fll->ref_src,
1421 false);
1422 if (fll->sync_src >= 0)
1423 arizona_apply_fll(arizona, fll->base + 0x10, sync,
1424 fll->sync_src, true);
1425 } else if (fll->sync_src >= 0) {
1426 regmap_update_bits(arizona->regmap, fll->base + 5,
1427 ARIZONA_FLL1_OUTDIV_MASK,
1428 sync->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
1429
1430 arizona_apply_fll(arizona, fll->base, sync,
1431 fll->sync_src, false);
1150 1432
1151 ret = arizona_calc_fll(fll, &cfg, 32768, Fout);
1152 if (ret != 0)
1153 return ret;
1154 } else {
1155 ret = arizona_calc_fll(fll, &cfg, Fref, Fout);
1156 if (ret != 0)
1157 return ret;
1158 }
1159 } else {
1160 regmap_update_bits(arizona->regmap, fll->base + 1,
1161 ARIZONA_FLL1_ENA, 0);
1162 regmap_update_bits(arizona->regmap, fll->base + 0x11, 1433 regmap_update_bits(arizona->regmap, fll->base + 0x11,
1163 ARIZONA_FLL1_SYNC_ENA, 0); 1434 ARIZONA_FLL1_SYNC_ENA, 0);
1164
1165 if (ena)
1166 pm_runtime_put_autosuspend(arizona->dev);
1167
1168 fll->fref = Fref;
1169 fll->fout = Fout;
1170
1171 return 0;
1172 }
1173
1174 regmap_update_bits(arizona->regmap, fll->base + 5,
1175 ARIZONA_FLL1_OUTDIV_MASK,
1176 cfg.outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
1177
1178 if (syncsrc >= 0) {
1179 arizona_apply_fll(arizona, fll->base, &cfg, syncsrc);
1180 arizona_apply_fll(arizona, fll->base + 0x10, &sync, source);
1181 } else { 1435 } else {
1182 arizona_apply_fll(arizona, fll->base, &cfg, source); 1436 arizona_fll_err(fll, "No clocks provided\n");
1437 return;
1183 } 1438 }
1184 1439
1185 if (!ena) 1440 /*
1441 * Increase the bandwidth if we're not using a low frequency
1442 * sync source.
1443 */
1444 if (fll->sync_src >= 0 && fll->sync_freq > 100000)
1445 regmap_update_bits(arizona->regmap, fll->base + 0x17,
1446 ARIZONA_FLL1_SYNC_BW, 0);
1447 else
1448 regmap_update_bits(arizona->regmap, fll->base + 0x17,
1449 ARIZONA_FLL1_SYNC_BW, ARIZONA_FLL1_SYNC_BW);
1450
1451 if (!arizona_is_enabled_fll(fll))
1186 pm_runtime_get(arizona->dev); 1452 pm_runtime_get(arizona->dev);
1187 1453
1188 /* Clear any pending completions */ 1454 /* Clear any pending completions */
@@ -1190,7 +1456,8 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
1190 1456
1191 regmap_update_bits(arizona->regmap, fll->base + 1, 1457 regmap_update_bits(arizona->regmap, fll->base + 1,
1192 ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA); 1458 ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
1193 if (syncsrc >= 0) 1459 if (fll->ref_src >= 0 && fll->sync_src >= 0 &&
1460 fll->ref_src != fll->sync_src)
1194 regmap_update_bits(arizona->regmap, fll->base + 0x11, 1461 regmap_update_bits(arizona->regmap, fll->base + 0x11,
1195 ARIZONA_FLL1_SYNC_ENA, 1462 ARIZONA_FLL1_SYNC_ENA,
1196 ARIZONA_FLL1_SYNC_ENA); 1463 ARIZONA_FLL1_SYNC_ENA);
@@ -1199,10 +1466,88 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
1199 msecs_to_jiffies(250)); 1466 msecs_to_jiffies(250));
1200 if (ret == 0) 1467 if (ret == 0)
1201 arizona_fll_warn(fll, "Timed out waiting for lock\n"); 1468 arizona_fll_warn(fll, "Timed out waiting for lock\n");
1469}
1470
1471static void arizona_disable_fll(struct arizona_fll *fll)
1472{
1473 struct arizona *arizona = fll->arizona;
1474 bool change;
1475
1476 regmap_update_bits_check(arizona->regmap, fll->base + 1,
1477 ARIZONA_FLL1_ENA, 0, &change);
1478 regmap_update_bits(arizona->regmap, fll->base + 0x11,
1479 ARIZONA_FLL1_SYNC_ENA, 0);
1480
1481 if (change)
1482 pm_runtime_put_autosuspend(arizona->dev);
1483}
1484
1485int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
1486 unsigned int Fref, unsigned int Fout)
1487{
1488 struct arizona_fll_cfg ref, sync;
1489 int ret;
1202 1490
1203 fll->fref = Fref; 1491 if (fll->ref_src == source && fll->ref_freq == Fref)
1492 return 0;
1493
1494 if (fll->fout && Fref > 0) {
1495 ret = arizona_calc_fll(fll, &ref, Fref, fll->fout);
1496 if (ret != 0)
1497 return ret;
1498
1499 if (fll->sync_src >= 0) {
1500 ret = arizona_calc_fll(fll, &sync, fll->sync_freq,
1501 fll->fout);
1502 if (ret != 0)
1503 return ret;
1504 }
1505 }
1506
1507 fll->ref_src = source;
1508 fll->ref_freq = Fref;
1509
1510 if (fll->fout && Fref > 0) {
1511 arizona_enable_fll(fll, &ref, &sync);
1512 }
1513
1514 return 0;
1515}
1516EXPORT_SYMBOL_GPL(arizona_set_fll_refclk);
1517
1518int arizona_set_fll(struct arizona_fll *fll, int source,
1519 unsigned int Fref, unsigned int Fout)
1520{
1521 struct arizona_fll_cfg ref, sync;
1522 int ret;
1523
1524 if (fll->sync_src == source &&
1525 fll->sync_freq == Fref && fll->fout == Fout)
1526 return 0;
1527
1528 if (Fout) {
1529 if (fll->ref_src >= 0) {
1530 ret = arizona_calc_fll(fll, &ref, fll->ref_freq,
1531 Fout);
1532 if (ret != 0)
1533 return ret;
1534 }
1535
1536 ret = arizona_calc_fll(fll, &sync, Fref, Fout);
1537 if (ret != 0)
1538 return ret;
1539 }
1540
1541 fll->sync_src = source;
1542 fll->sync_freq = Fref;
1204 fll->fout = Fout; 1543 fll->fout = Fout;
1205 1544
1545 if (Fout) {
1546 arizona_enable_fll(fll, &ref, &sync);
1547 } else {
1548 arizona_disable_fll(fll);
1549 }
1550
1206 return 0; 1551 return 0;
1207} 1552}
1208EXPORT_SYMBOL_GPL(arizona_set_fll); 1553EXPORT_SYMBOL_GPL(arizona_set_fll);
@@ -1211,12 +1556,26 @@ int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
1211 int ok_irq, struct arizona_fll *fll) 1556 int ok_irq, struct arizona_fll *fll)
1212{ 1557{
1213 int ret; 1558 int ret;
1559 unsigned int val;
1214 1560
1215 init_completion(&fll->ok); 1561 init_completion(&fll->ok);
1216 1562
1217 fll->id = id; 1563 fll->id = id;
1218 fll->base = base; 1564 fll->base = base;
1219 fll->arizona = arizona; 1565 fll->arizona = arizona;
1566 fll->sync_src = ARIZONA_FLL_SRC_NONE;
1567
1568 /* Configure default refclk to 32kHz if we have one */
1569 regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val);
1570 switch (val & ARIZONA_CLK_32K_SRC_MASK) {
1571 case ARIZONA_CLK_SRC_MCLK1:
1572 case ARIZONA_CLK_SRC_MCLK2:
1573 fll->ref_src = val & ARIZONA_CLK_32K_SRC_MASK;
1574 break;
1575 default:
1576 fll->ref_src = ARIZONA_FLL_SRC_NONE;
1577 }
1578 fll->ref_freq = 32768;
1220 1579
1221 snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id); 1580 snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id);
1222 snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name), 1581 snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name),
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h
index 13dd2916b721..af39f1006427 100644
--- a/sound/soc/codecs/arizona.h
+++ b/sound/soc/codecs/arizona.h
@@ -32,6 +32,7 @@
32#define ARIZONA_CLK_SRC_AIF2BCLK 0x9 32#define ARIZONA_CLK_SRC_AIF2BCLK 0x9
33#define ARIZONA_CLK_SRC_AIF3BCLK 0xa 33#define ARIZONA_CLK_SRC_AIF3BCLK 0xa
34 34
35#define ARIZONA_FLL_SRC_NONE -1
35#define ARIZONA_FLL_SRC_MCLK1 0 36#define ARIZONA_FLL_SRC_MCLK1 0
36#define ARIZONA_FLL_SRC_MCLK2 1 37#define ARIZONA_FLL_SRC_MCLK2 1
37#define ARIZONA_FLL_SRC_SLIMCLK 3 38#define ARIZONA_FLL_SRC_SLIMCLK 3
@@ -48,6 +49,14 @@
48#define ARIZONA_MIXER_VOL_SHIFT 1 49#define ARIZONA_MIXER_VOL_SHIFT 1
49#define ARIZONA_MIXER_VOL_WIDTH 7 50#define ARIZONA_MIXER_VOL_WIDTH 7
50 51
52#define ARIZONA_CLK_6MHZ 0
53#define ARIZONA_CLK_12MHZ 1
54#define ARIZONA_CLK_24MHZ 2
55#define ARIZONA_CLK_49MHZ 3
56#define ARIZONA_CLK_73MHZ 4
57#define ARIZONA_CLK_98MHZ 5
58#define ARIZONA_CLK_147MHZ 6
59
51#define ARIZONA_MAX_DAI 4 60#define ARIZONA_MAX_DAI 4
52#define ARIZONA_MAX_ADSP 4 61#define ARIZONA_MAX_ADSP 4
53 62
@@ -64,6 +73,12 @@ struct arizona_priv {
64 int sysclk; 73 int sysclk;
65 int asyncclk; 74 int asyncclk;
66 struct arizona_dai_priv dai[ARIZONA_MAX_DAI]; 75 struct arizona_dai_priv dai[ARIZONA_MAX_DAI];
76
77 int num_inputs;
78 unsigned int in_pending;
79
80 unsigned int spk_ena:2;
81 unsigned int spk_ena_pending:1;
67}; 82};
68 83
69#define ARIZONA_NUM_MIXER_INPUTS 99 84#define ARIZONA_NUM_MIXER_INPUTS 99
@@ -165,6 +180,12 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
165 ARIZONA_MIXER_ROUTES(name, name "L"), \ 180 ARIZONA_MIXER_ROUTES(name, name "L"), \
166 ARIZONA_MIXER_ROUTES(name, name "R") 181 ARIZONA_MIXER_ROUTES(name, name "R")
167 182
183#define ARIZONA_RATE_ENUM_SIZE 4
184extern const char *arizona_rate_text[ARIZONA_RATE_ENUM_SIZE];
185extern const int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE];
186
187extern const struct soc_enum arizona_isrc_fsl[];
188
168extern const struct soc_enum arizona_in_vi_ramp; 189extern const struct soc_enum arizona_in_vi_ramp;
169extern const struct soc_enum arizona_in_vd_ramp; 190extern const struct soc_enum arizona_in_vd_ramp;
170 191
@@ -201,8 +222,12 @@ struct arizona_fll {
201 unsigned int base; 222 unsigned int base;
202 unsigned int vco_mult; 223 unsigned int vco_mult;
203 struct completion ok; 224 struct completion ok;
204 unsigned int fref; 225
205 unsigned int fout; 226 unsigned int fout;
227 int sync_src;
228 unsigned int sync_freq;
229 int ref_src;
230 unsigned int ref_freq;
206 231
207 char lock_name[ARIZONA_FLL_NAME_LEN]; 232 char lock_name[ARIZONA_FLL_NAME_LEN];
208 char clock_ok_name[ARIZONA_FLL_NAME_LEN]; 233 char clock_ok_name[ARIZONA_FLL_NAME_LEN];
@@ -210,9 +235,13 @@ struct arizona_fll {
210 235
211extern int arizona_init_fll(struct arizona *arizona, int id, int base, 236extern int arizona_init_fll(struct arizona *arizona, int id, int base,
212 int lock_irq, int ok_irq, struct arizona_fll *fll); 237 int lock_irq, int ok_irq, struct arizona_fll *fll);
238extern int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
239 unsigned int Fref, unsigned int Fout);
213extern int arizona_set_fll(struct arizona_fll *fll, int source, 240extern int arizona_set_fll(struct arizona_fll *fll, int source,
214 unsigned int Fref, unsigned int Fout); 241 unsigned int Fref, unsigned int Fout);
215 242
243extern int arizona_init_spk(struct snd_soc_codec *codec);
244
216extern int arizona_init_dai(struct arizona_priv *priv, int dai); 245extern int arizona_init_dai(struct arizona_priv *priv, int dai);
217 246
218int arizona_set_output_mode(struct snd_soc_codec *codec, int output, 247int arizona_set_output_mode(struct snd_soc_codec *codec, int output,
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c
index 2415a4118dbd..03036b326732 100644
--- a/sound/soc/codecs/cs4271.c
+++ b/sound/soc/codecs/cs4271.c
@@ -39,17 +39,15 @@
39 39
40/* 40/*
41 * CS4271 registers 41 * CS4271 registers
42 * High byte represents SPI chip address (0x10) + write command (0)
43 * Low byte - codec register address
44 */ 42 */
45#define CS4271_MODE1 0x2001 /* Mode Control 1 */ 43#define CS4271_MODE1 0x01 /* Mode Control 1 */
46#define CS4271_DACCTL 0x2002 /* DAC Control */ 44#define CS4271_DACCTL 0x02 /* DAC Control */
47#define CS4271_DACVOL 0x2003 /* DAC Volume & Mixing Control */ 45#define CS4271_DACVOL 0x03 /* DAC Volume & Mixing Control */
48#define CS4271_VOLA 0x2004 /* DAC Channel A Volume Control */ 46#define CS4271_VOLA 0x04 /* DAC Channel A Volume Control */
49#define CS4271_VOLB 0x2005 /* DAC Channel B Volume Control */ 47#define CS4271_VOLB 0x05 /* DAC Channel B Volume Control */
50#define CS4271_ADCCTL 0x2006 /* ADC Control */ 48#define CS4271_ADCCTL 0x06 /* ADC Control */
51#define CS4271_MODE2 0x2007 /* Mode Control 2 */ 49#define CS4271_MODE2 0x07 /* Mode Control 2 */
52#define CS4271_CHIPID 0x2008 /* Chip ID */ 50#define CS4271_CHIPID 0x08 /* Chip ID */
53 51
54#define CS4271_FIRSTREG CS4271_MODE1 52#define CS4271_FIRSTREG CS4271_MODE1
55#define CS4271_LASTREG CS4271_MODE2 53#define CS4271_LASTREG CS4271_MODE2
@@ -144,23 +142,27 @@
144 * Array do not include Chip ID, as codec driver does not use 142 * Array do not include Chip ID, as codec driver does not use
145 * registers read operations at all 143 * registers read operations at all
146 */ 144 */
147static const u8 cs4271_dflt_reg[CS4271_NR_REGS] = { 145static const struct reg_default cs4271_reg_defaults[] = {
148 0, 146 { CS4271_MODE1, 0, },
149 0, 147 { CS4271_DACCTL, CS4271_DACCTL_AMUTE, },
150 CS4271_DACCTL_AMUTE, 148 { CS4271_DACVOL, CS4271_DACVOL_SOFT | CS4271_DACVOL_ATAPI_AL_BR, },
151 CS4271_DACVOL_SOFT | CS4271_DACVOL_ATAPI_AL_BR, 149 { CS4271_VOLA, 0, },
152 0, 150 { CS4271_VOLB, 0, },
153 0, 151 { CS4271_ADCCTL, 0, },
154 0, 152 { CS4271_MODE2, 0, },
155 0,
156}; 153};
157 154
155static bool cs4271_volatile_reg(struct device *dev, unsigned int reg)
156{
157 return reg == CS4271_CHIPID;
158}
159
158struct cs4271_private { 160struct cs4271_private {
159 /* SND_SOC_I2C or SND_SOC_SPI */ 161 /* SND_SOC_I2C or SND_SOC_SPI */
160 enum snd_soc_control_type bus_type;
161 unsigned int mclk; 162 unsigned int mclk;
162 bool master; 163 bool master;
163 bool deemph; 164 bool deemph;
165 struct regmap *regmap;
164 /* Current sample rate for de-emphasis control */ 166 /* Current sample rate for de-emphasis control */
165 int rate; 167 int rate;
166 /* GPIO driving Reset pin, if any */ 168 /* GPIO driving Reset pin, if any */
@@ -210,14 +212,14 @@ static int cs4271_set_dai_fmt(struct snd_soc_dai *codec_dai,
210 switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { 212 switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
211 case SND_SOC_DAIFMT_LEFT_J: 213 case SND_SOC_DAIFMT_LEFT_J:
212 val |= CS4271_MODE1_DAC_DIF_LJ; 214 val |= CS4271_MODE1_DAC_DIF_LJ;
213 ret = snd_soc_update_bits(codec, CS4271_ADCCTL, 215 ret = regmap_update_bits(cs4271->regmap, CS4271_ADCCTL,
214 CS4271_ADCCTL_ADC_DIF_MASK, CS4271_ADCCTL_ADC_DIF_LJ); 216 CS4271_ADCCTL_ADC_DIF_MASK, CS4271_ADCCTL_ADC_DIF_LJ);
215 if (ret < 0) 217 if (ret < 0)
216 return ret; 218 return ret;
217 break; 219 break;
218 case SND_SOC_DAIFMT_I2S: 220 case SND_SOC_DAIFMT_I2S:
219 val |= CS4271_MODE1_DAC_DIF_I2S; 221 val |= CS4271_MODE1_DAC_DIF_I2S;
220 ret = snd_soc_update_bits(codec, CS4271_ADCCTL, 222 ret = regmap_update_bits(cs4271->regmap, CS4271_ADCCTL,
221 CS4271_ADCCTL_ADC_DIF_MASK, CS4271_ADCCTL_ADC_DIF_I2S); 223 CS4271_ADCCTL_ADC_DIF_MASK, CS4271_ADCCTL_ADC_DIF_I2S);
222 if (ret < 0) 224 if (ret < 0)
223 return ret; 225 return ret;
@@ -227,7 +229,7 @@ static int cs4271_set_dai_fmt(struct snd_soc_dai *codec_dai,
227 return -EINVAL; 229 return -EINVAL;
228 } 230 }
229 231
230 ret = snd_soc_update_bits(codec, CS4271_MODE1, 232 ret = regmap_update_bits(cs4271->regmap, CS4271_MODE1,
231 CS4271_MODE1_DAC_DIF_MASK | CS4271_MODE1_MASTER, val); 233 CS4271_MODE1_DAC_DIF_MASK | CS4271_MODE1_MASTER, val);
232 if (ret < 0) 234 if (ret < 0)
233 return ret; 235 return ret;
@@ -252,7 +254,7 @@ static int cs4271_set_deemph(struct snd_soc_codec *codec)
252 val <<= 4; 254 val <<= 4;
253 } 255 }
254 256
255 ret = snd_soc_update_bits(codec, CS4271_DACCTL, 257 ret = regmap_update_bits(cs4271->regmap, CS4271_DACCTL,
256 CS4271_DACCTL_DEM_MASK, val); 258 CS4271_DACCTL_DEM_MASK, val);
257 if (ret < 0) 259 if (ret < 0)
258 return ret; 260 return ret;
@@ -341,14 +343,14 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream,
341 !dai->capture_active) || 343 !dai->capture_active) ||
342 (substream->stream == SNDRV_PCM_STREAM_CAPTURE && 344 (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
343 !dai->playback_active)) { 345 !dai->playback_active)) {
344 ret = snd_soc_update_bits(codec, CS4271_MODE2, 346 ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2,
345 CS4271_MODE2_PDN, 347 CS4271_MODE2_PDN,
346 CS4271_MODE2_PDN); 348 CS4271_MODE2_PDN);
347 if (ret < 0) 349 if (ret < 0)
348 return ret; 350 return ret;
349 351
350 ret = snd_soc_update_bits(codec, CS4271_MODE2, 352 ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2,
351 CS4271_MODE2_PDN, 0); 353 CS4271_MODE2_PDN, 0);
352 if (ret < 0) 354 if (ret < 0)
353 return ret; 355 return ret;
354 } 356 }
@@ -378,7 +380,7 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream,
378 380
379 val |= cs4271_clk_tab[i].ratio_mask; 381 val |= cs4271_clk_tab[i].ratio_mask;
380 382
381 ret = snd_soc_update_bits(codec, CS4271_MODE1, 383 ret = regmap_update_bits(cs4271->regmap, CS4271_MODE1,
382 CS4271_MODE1_MODE_MASK | CS4271_MODE1_DIV_MASK, val); 384 CS4271_MODE1_MODE_MASK | CS4271_MODE1_DIV_MASK, val);
383 if (ret < 0) 385 if (ret < 0)
384 return ret; 386 return ret;
@@ -386,22 +388,29 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream,
386 return cs4271_set_deemph(codec); 388 return cs4271_set_deemph(codec);
387} 389}
388 390
389static int cs4271_digital_mute(struct snd_soc_dai *dai, int mute) 391static int cs4271_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
390{ 392{
391 struct snd_soc_codec *codec = dai->codec; 393 struct snd_soc_codec *codec = dai->codec;
394 struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
392 int ret; 395 int ret;
393 int val_a = 0; 396 int val_a = 0;
394 int val_b = 0; 397 int val_b = 0;
395 398
399 if (stream != SNDRV_PCM_STREAM_PLAYBACK)
400 return 0;
401
396 if (mute) { 402 if (mute) {
397 val_a = CS4271_VOLA_MUTE; 403 val_a = CS4271_VOLA_MUTE;
398 val_b = CS4271_VOLB_MUTE; 404 val_b = CS4271_VOLB_MUTE;
399 } 405 }
400 406
401 ret = snd_soc_update_bits(codec, CS4271_VOLA, CS4271_VOLA_MUTE, val_a); 407 ret = regmap_update_bits(cs4271->regmap, CS4271_VOLA,
408 CS4271_VOLA_MUTE, val_a);
402 if (ret < 0) 409 if (ret < 0)
403 return ret; 410 return ret;
404 ret = snd_soc_update_bits(codec, CS4271_VOLB, CS4271_VOLB_MUTE, val_b); 411
412 ret = regmap_update_bits(cs4271->regmap, CS4271_VOLB,
413 CS4271_VOLB_MUTE, val_b);
405 if (ret < 0) 414 if (ret < 0)
406 return ret; 415 return ret;
407 416
@@ -436,7 +445,7 @@ static const struct snd_soc_dai_ops cs4271_dai_ops = {
436 .hw_params = cs4271_hw_params, 445 .hw_params = cs4271_hw_params,
437 .set_sysclk = cs4271_set_dai_sysclk, 446 .set_sysclk = cs4271_set_dai_sysclk,
438 .set_fmt = cs4271_set_dai_fmt, 447 .set_fmt = cs4271_set_dai_fmt,
439 .digital_mute = cs4271_digital_mute, 448 .mute_stream = cs4271_mute_stream,
440}; 449};
441 450
442static struct snd_soc_dai_driver cs4271_dai = { 451static struct snd_soc_dai_driver cs4271_dai = {
@@ -463,25 +472,33 @@ static struct snd_soc_dai_driver cs4271_dai = {
463static int cs4271_soc_suspend(struct snd_soc_codec *codec) 472static int cs4271_soc_suspend(struct snd_soc_codec *codec)
464{ 473{
465 int ret; 474 int ret;
475 struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
476
466 /* Set power-down bit */ 477 /* Set power-down bit */
467 ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, 478 ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2,
468 CS4271_MODE2_PDN); 479 CS4271_MODE2_PDN, CS4271_MODE2_PDN);
469 if (ret < 0) 480 if (ret < 0)
470 return ret; 481 return ret;
482
471 return 0; 483 return 0;
472} 484}
473 485
474static int cs4271_soc_resume(struct snd_soc_codec *codec) 486static int cs4271_soc_resume(struct snd_soc_codec *codec)
475{ 487{
476 int ret; 488 int ret;
489 struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
490
477 /* Restore codec state */ 491 /* Restore codec state */
478 ret = snd_soc_cache_sync(codec); 492 ret = regcache_sync(cs4271->regmap);
479 if (ret < 0) 493 if (ret < 0)
480 return ret; 494 return ret;
495
481 /* then disable the power-down bit */ 496 /* then disable the power-down bit */
482 ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, 0); 497 ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2,
498 CS4271_MODE2_PDN, 0);
483 if (ret < 0) 499 if (ret < 0)
484 return ret; 500 return ret;
501
485 return 0; 502 return 0;
486} 503}
487#else 504#else
@@ -542,40 +559,22 @@ static int cs4271_probe(struct snd_soc_codec *codec)
542 559
543 cs4271->gpio_nreset = gpio_nreset; 560 cs4271->gpio_nreset = gpio_nreset;
544 561
545 /* 562 ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2,
546 * In case of I2C, chip address specified in board data. 563 CS4271_MODE2_PDN | CS4271_MODE2_CPEN,
547 * So cache IO operations use 8 bit codec register address. 564 CS4271_MODE2_PDN | CS4271_MODE2_CPEN);
548 * In case of SPI, chip address and register address
549 * passed together as 16 bit value.
550 * Anyway, register address is masked with 0xFF inside
551 * soc-cache code.
552 */
553 if (cs4271->bus_type == SND_SOC_SPI)
554 ret = snd_soc_codec_set_cache_io(codec, 16, 8,
555 cs4271->bus_type);
556 else
557 ret = snd_soc_codec_set_cache_io(codec, 8, 8,
558 cs4271->bus_type);
559 if (ret) {
560 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
561 return ret;
562 }
563
564 ret = snd_soc_update_bits(codec, CS4271_MODE2,
565 CS4271_MODE2_PDN | CS4271_MODE2_CPEN,
566 CS4271_MODE2_PDN | CS4271_MODE2_CPEN);
567 if (ret < 0) 565 if (ret < 0)
568 return ret; 566 return ret;
569 ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, 0); 567 ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2,
568 CS4271_MODE2_PDN, 0);
570 if (ret < 0) 569 if (ret < 0)
571 return ret; 570 return ret;
572 /* Power-up sequence requires 85 uS */ 571 /* Power-up sequence requires 85 uS */
573 udelay(85); 572 udelay(85);
574 573
575 if (amutec_eq_bmutec) 574 if (amutec_eq_bmutec)
576 snd_soc_update_bits(codec, CS4271_MODE2, 575 regmap_update_bits(cs4271->regmap, CS4271_MODE2,
577 CS4271_MODE2_MUTECAEQUB, 576 CS4271_MODE2_MUTECAEQUB,
578 CS4271_MODE2_MUTECAEQUB); 577 CS4271_MODE2_MUTECAEQUB);
579 578
580 return snd_soc_add_codec_controls(codec, cs4271_snd_controls, 579 return snd_soc_add_codec_controls(codec, cs4271_snd_controls,
581 ARRAY_SIZE(cs4271_snd_controls)); 580 ARRAY_SIZE(cs4271_snd_controls));
@@ -597,13 +596,24 @@ static struct snd_soc_codec_driver soc_codec_dev_cs4271 = {
597 .remove = cs4271_remove, 596 .remove = cs4271_remove,
598 .suspend = cs4271_soc_suspend, 597 .suspend = cs4271_soc_suspend,
599 .resume = cs4271_soc_resume, 598 .resume = cs4271_soc_resume,
600 .reg_cache_default = cs4271_dflt_reg,
601 .reg_cache_size = ARRAY_SIZE(cs4271_dflt_reg),
602 .reg_word_size = sizeof(cs4271_dflt_reg[0]),
603 .compress_type = SND_SOC_FLAT_COMPRESSION,
604}; 599};
605 600
606#if defined(CONFIG_SPI_MASTER) 601#if defined(CONFIG_SPI_MASTER)
602
603static const struct regmap_config cs4271_spi_regmap = {
604 .reg_bits = 16,
605 .val_bits = 8,
606 .max_register = CS4271_LASTREG,
607 .read_flag_mask = 0x21,
608 .write_flag_mask = 0x20,
609
610 .reg_defaults = cs4271_reg_defaults,
611 .num_reg_defaults = ARRAY_SIZE(cs4271_reg_defaults),
612 .cache_type = REGCACHE_RBTREE,
613
614 .volatile_reg = cs4271_volatile_reg,
615};
616
607static int cs4271_spi_probe(struct spi_device *spi) 617static int cs4271_spi_probe(struct spi_device *spi)
608{ 618{
609 struct cs4271_private *cs4271; 619 struct cs4271_private *cs4271;
@@ -613,7 +623,9 @@ static int cs4271_spi_probe(struct spi_device *spi)
613 return -ENOMEM; 623 return -ENOMEM;
614 624
615 spi_set_drvdata(spi, cs4271); 625 spi_set_drvdata(spi, cs4271);
616 cs4271->bus_type = SND_SOC_SPI; 626 cs4271->regmap = devm_regmap_init_spi(spi, &cs4271_spi_regmap);
627 if (IS_ERR(cs4271->regmap))
628 return PTR_ERR(cs4271->regmap);
617 629
618 return snd_soc_register_codec(&spi->dev, &soc_codec_dev_cs4271, 630 return snd_soc_register_codec(&spi->dev, &soc_codec_dev_cs4271,
619 &cs4271_dai, 1); 631 &cs4271_dai, 1);
@@ -643,6 +655,18 @@ static const struct i2c_device_id cs4271_i2c_id[] = {
643}; 655};
644MODULE_DEVICE_TABLE(i2c, cs4271_i2c_id); 656MODULE_DEVICE_TABLE(i2c, cs4271_i2c_id);
645 657
658static const struct regmap_config cs4271_i2c_regmap = {
659 .reg_bits = 8,
660 .val_bits = 8,
661 .max_register = CS4271_LASTREG,
662
663 .reg_defaults = cs4271_reg_defaults,
664 .num_reg_defaults = ARRAY_SIZE(cs4271_reg_defaults),
665 .cache_type = REGCACHE_RBTREE,
666
667 .volatile_reg = cs4271_volatile_reg,
668};
669
646static int cs4271_i2c_probe(struct i2c_client *client, 670static int cs4271_i2c_probe(struct i2c_client *client,
647 const struct i2c_device_id *id) 671 const struct i2c_device_id *id)
648{ 672{
@@ -653,7 +677,9 @@ static int cs4271_i2c_probe(struct i2c_client *client,
653 return -ENOMEM; 677 return -ENOMEM;
654 678
655 i2c_set_clientdata(client, cs4271); 679 i2c_set_clientdata(client, cs4271);
656 cs4271->bus_type = SND_SOC_I2C; 680 cs4271->regmap = devm_regmap_init_i2c(client, &cs4271_i2c_regmap);
681 if (IS_ERR(cs4271->regmap))
682 return PTR_ERR(cs4271->regmap);
657 683
658 return snd_soc_register_codec(&client->dev, &soc_codec_dev_cs4271, 684 return snd_soc_register_codec(&client->dev, &soc_codec_dev_cs4271,
659 &cs4271_dai, 1); 685 &cs4271_dai, 1);
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c
index 6361dab48bd1..3b20c86cdb01 100644
--- a/sound/soc/codecs/cs42l73.c
+++ b/sound/soc/codecs/cs42l73.c
@@ -1180,7 +1180,11 @@ static int cs42l73_pcm_hw_params(struct snd_pcm_substream *substream,
1180 priv->config[id].mmcc &= 0xC0; 1180 priv->config[id].mmcc &= 0xC0;
1181 priv->config[id].mmcc |= cs42l73_mclk_coeffs[mclk_coeff].mmcc; 1181 priv->config[id].mmcc |= cs42l73_mclk_coeffs[mclk_coeff].mmcc;
1182 priv->config[id].spc &= 0xFC; 1182 priv->config[id].spc &= 0xFC;
1183 priv->config[id].spc |= MCK_SCLK_MCLK; 1183 /* Use SCLK=64*Fs if internal MCLK >= 6.4MHz */
1184 if (priv->mclk >= 6400000)
1185 priv->config[id].spc |= MCK_SCLK_64FS;
1186 else
1187 priv->config[id].spc |= MCK_SCLK_MCLK;
1184 } else { 1188 } else {
1185 /* CS42L73 Slave */ 1189 /* CS42L73 Slave */
1186 priv->config[id].spc &= 0xFC; 1190 priv->config[id].spc &= 0xFC;
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
index a4c16fd70f77..3eeada57e87d 100644
--- a/sound/soc/codecs/max98088.c
+++ b/sound/soc/codecs/max98088.c
@@ -739,14 +739,32 @@ static const unsigned int max98088_micboost_tlv[] = {
739 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0), 739 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0),
740}; 740};
741 741
742static const unsigned int max98088_hp_tlv[] = {
743 TLV_DB_RANGE_HEAD(5),
744 0, 6, TLV_DB_SCALE_ITEM(-6700, 400, 0),
745 7, 14, TLV_DB_SCALE_ITEM(-4000, 300, 0),
746 15, 21, TLV_DB_SCALE_ITEM(-1700, 200, 0),
747 22, 27, TLV_DB_SCALE_ITEM(-400, 100, 0),
748 28, 31, TLV_DB_SCALE_ITEM(150, 50, 0),
749};
750
751static const unsigned int max98088_spk_tlv[] = {
752 TLV_DB_RANGE_HEAD(5),
753 0, 6, TLV_DB_SCALE_ITEM(-6200, 400, 0),
754 7, 14, TLV_DB_SCALE_ITEM(-3500, 300, 0),
755 15, 21, TLV_DB_SCALE_ITEM(-1200, 200, 0),
756 22, 27, TLV_DB_SCALE_ITEM(100, 100, 0),
757 28, 31, TLV_DB_SCALE_ITEM(650, 50, 0),
758};
759
742static const struct snd_kcontrol_new max98088_snd_controls[] = { 760static const struct snd_kcontrol_new max98088_snd_controls[] = {
743 761
744 SOC_DOUBLE_R("Headphone Volume", M98088_REG_39_LVL_HP_L, 762 SOC_DOUBLE_R_TLV("Headphone Volume", M98088_REG_39_LVL_HP_L,
745 M98088_REG_3A_LVL_HP_R, 0, 31, 0), 763 M98088_REG_3A_LVL_HP_R, 0, 31, 0, max98088_hp_tlv),
746 SOC_DOUBLE_R("Speaker Volume", M98088_REG_3D_LVL_SPK_L, 764 SOC_DOUBLE_R_TLV("Speaker Volume", M98088_REG_3D_LVL_SPK_L,
747 M98088_REG_3E_LVL_SPK_R, 0, 31, 0), 765 M98088_REG_3E_LVL_SPK_R, 0, 31, 0, max98088_spk_tlv),
748 SOC_DOUBLE_R("Receiver Volume", M98088_REG_3B_LVL_REC_L, 766 SOC_DOUBLE_R_TLV("Receiver Volume", M98088_REG_3B_LVL_REC_L,
749 M98088_REG_3C_LVL_REC_R, 0, 31, 0), 767 M98088_REG_3C_LVL_REC_R, 0, 31, 0, max98088_spk_tlv),
750 768
751 SOC_DOUBLE_R("Headphone Switch", M98088_REG_39_LVL_HP_L, 769 SOC_DOUBLE_R("Headphone Switch", M98088_REG_39_LVL_HP_L,
752 M98088_REG_3A_LVL_HP_R, 7, 1, 1), 770 M98088_REG_3A_LVL_HP_R, 7, 1, 1),
@@ -2006,7 +2024,7 @@ static int max98088_probe(struct snd_soc_codec *codec)
2006 ret); 2024 ret);
2007 goto err_access; 2025 goto err_access;
2008 } 2026 }
2009 dev_info(codec->dev, "revision %c\n", ret + 'A'); 2027 dev_info(codec->dev, "revision %c\n", ret - 0x40 + 'A');
2010 2028
2011 snd_soc_write(codec, M98088_REG_51_PWR_SYS, M98088_PWRSV); 2029 snd_soc_write(codec, M98088_REG_51_PWR_SYS, M98088_PWRSV);
2012 2030
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c
index fc176044994d..ce0d36412c97 100644
--- a/sound/soc/codecs/max98090.c
+++ b/sound/soc/codecs/max98090.c
@@ -23,8 +23,6 @@
23#include <sound/max98090.h> 23#include <sound/max98090.h>
24#include "max98090.h" 24#include "max98090.h"
25 25
26#include <linux/version.h>
27
28#define DEBUG 26#define DEBUG
29#define EXTMIC_METHOD 27#define EXTMIC_METHOD
30#define EXTMIC_METHOD_TEST 28#define EXTMIC_METHOD_TEST
@@ -509,16 +507,16 @@ static int max98090_put_enab_tlv(struct snd_kcontrol *kcontrol,
509 return 0; 507 return 0;
510} 508}
511 509
512static const char * max98090_perf_pwr_text[] = 510static const char *max98090_perf_pwr_text[] =
513 { "High Performance", "Low Power" }; 511 { "High Performance", "Low Power" };
514static const char * max98090_pwr_perf_text[] = 512static const char *max98090_pwr_perf_text[] =
515 { "Low Power", "High Performance" }; 513 { "Low Power", "High Performance" };
516 514
517static const struct soc_enum max98090_vcmbandgap_enum = 515static const struct soc_enum max98090_vcmbandgap_enum =
518 SOC_ENUM_SINGLE(M98090_REG_BIAS_CONTROL, M98090_VCM_MODE_SHIFT, 516 SOC_ENUM_SINGLE(M98090_REG_BIAS_CONTROL, M98090_VCM_MODE_SHIFT,
519 ARRAY_SIZE(max98090_pwr_perf_text), max98090_pwr_perf_text); 517 ARRAY_SIZE(max98090_pwr_perf_text), max98090_pwr_perf_text);
520 518
521static const char * max98090_osr128_text[] = { "64*fs", "128*fs" }; 519static const char *max98090_osr128_text[] = { "64*fs", "128*fs" };
522 520
523static const struct soc_enum max98090_osr128_enum = 521static const struct soc_enum max98090_osr128_enum =
524 SOC_ENUM_SINGLE(M98090_REG_ADC_CONTROL, M98090_OSR128_SHIFT, 522 SOC_ENUM_SINGLE(M98090_REG_ADC_CONTROL, M98090_OSR128_SHIFT,
@@ -535,28 +533,28 @@ static const struct soc_enum max98090_filter_dmic34mode_enum =
535 M98090_FLT_DMIC34MODE_SHIFT, 533 M98090_FLT_DMIC34MODE_SHIFT,
536 ARRAY_SIZE(max98090_mode_text), max98090_mode_text); 534 ARRAY_SIZE(max98090_mode_text), max98090_mode_text);
537 535
538static const char * max98090_drcatk_text[] = 536static const char *max98090_drcatk_text[] =
539 { "0.5ms", "1ms", "5ms", "10ms", "25ms", "50ms", "100ms", "200ms" }; 537 { "0.5ms", "1ms", "5ms", "10ms", "25ms", "50ms", "100ms", "200ms" };
540 538
541static const struct soc_enum max98090_drcatk_enum = 539static const struct soc_enum max98090_drcatk_enum =
542 SOC_ENUM_SINGLE(M98090_REG_DRC_TIMING, M98090_DRCATK_SHIFT, 540 SOC_ENUM_SINGLE(M98090_REG_DRC_TIMING, M98090_DRCATK_SHIFT,
543 ARRAY_SIZE(max98090_drcatk_text), max98090_drcatk_text); 541 ARRAY_SIZE(max98090_drcatk_text), max98090_drcatk_text);
544 542
545static const char * max98090_drcrls_text[] = 543static const char *max98090_drcrls_text[] =
546 { "8s", "4s", "2s", "1s", "0.5s", "0.25s", "0.125s", "0.0625s" }; 544 { "8s", "4s", "2s", "1s", "0.5s", "0.25s", "0.125s", "0.0625s" };
547 545
548static const struct soc_enum max98090_drcrls_enum = 546static const struct soc_enum max98090_drcrls_enum =
549 SOC_ENUM_SINGLE(M98090_REG_DRC_TIMING, M98090_DRCRLS_SHIFT, 547 SOC_ENUM_SINGLE(M98090_REG_DRC_TIMING, M98090_DRCRLS_SHIFT,
550 ARRAY_SIZE(max98090_drcrls_text), max98090_drcrls_text); 548 ARRAY_SIZE(max98090_drcrls_text), max98090_drcrls_text);
551 549
552static const char * max98090_alccmp_text[] = 550static const char *max98090_alccmp_text[] =
553 { "1:1", "1:1.5", "1:2", "1:4", "1:INF" }; 551 { "1:1", "1:1.5", "1:2", "1:4", "1:INF" };
554 552
555static const struct soc_enum max98090_alccmp_enum = 553static const struct soc_enum max98090_alccmp_enum =
556 SOC_ENUM_SINGLE(M98090_REG_DRC_COMPRESSOR, M98090_DRCCMP_SHIFT, 554 SOC_ENUM_SINGLE(M98090_REG_DRC_COMPRESSOR, M98090_DRCCMP_SHIFT,
557 ARRAY_SIZE(max98090_alccmp_text), max98090_alccmp_text); 555 ARRAY_SIZE(max98090_alccmp_text), max98090_alccmp_text);
558 556
559static const char * max98090_drcexp_text[] = { "1:1", "2:1", "3:1" }; 557static const char *max98090_drcexp_text[] = { "1:1", "2:1", "3:1" };
560 558
561static const struct soc_enum max98090_drcexp_enum = 559static const struct soc_enum max98090_drcexp_enum =
562 SOC_ENUM_SINGLE(M98090_REG_DRC_EXPANDER, M98090_DRCEXP_SHIFT, 560 SOC_ENUM_SINGLE(M98090_REG_DRC_EXPANDER, M98090_DRCEXP_SHIFT,
@@ -859,7 +857,7 @@ static const struct soc_enum mic2_mux_enum =
859static const struct snd_kcontrol_new max98090_mic2_mux = 857static const struct snd_kcontrol_new max98090_mic2_mux =
860 SOC_DAPM_ENUM("MIC2 Mux", mic2_mux_enum); 858 SOC_DAPM_ENUM("MIC2 Mux", mic2_mux_enum);
861 859
862static const char * max98090_micpre_text[] = { "Off", "On" }; 860static const char *max98090_micpre_text[] = { "Off", "On" };
863 861
864static const struct soc_enum max98090_pa1en_enum = 862static const struct soc_enum max98090_pa1en_enum =
865 SOC_ENUM_SINGLE(M98090_REG_MIC1_INPUT_LEVEL, M98090_MIC_PA1EN_SHIFT, 863 SOC_ENUM_SINGLE(M98090_REG_MIC1_INPUT_LEVEL, M98090_MIC_PA1EN_SHIFT,
@@ -1703,9 +1701,8 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai,
1703 * seen for the case of TDM mode. The remaining cases have 1701 * seen for the case of TDM mode. The remaining cases have
1704 * normal logic. 1702 * normal logic.
1705 */ 1703 */
1706 if (max98090->tdm_slots > 1) { 1704 if (max98090->tdm_slots > 1)
1707 regval ^= M98090_BCI_MASK; 1705 regval ^= M98090_BCI_MASK;
1708 }
1709 1706
1710 snd_soc_write(codec, 1707 snd_soc_write(codec,
1711 M98090_REG_INTERFACE_FORMAT, regval); 1708 M98090_REG_INTERFACE_FORMAT, regval);
@@ -2059,17 +2056,14 @@ static irqreturn_t max98090_interrupt(int irq, void *data)
2059 if (!active) 2056 if (!active)
2060 return IRQ_NONE; 2057 return IRQ_NONE;
2061 2058
2062 if (active & M98090_CLD_MASK) { 2059 if (active & M98090_CLD_MASK)
2063 dev_err(codec->dev, "M98090_CLD_MASK\n"); 2060 dev_err(codec->dev, "M98090_CLD_MASK\n");
2064 }
2065 2061
2066 if (active & M98090_SLD_MASK) { 2062 if (active & M98090_SLD_MASK)
2067 dev_dbg(codec->dev, "M98090_SLD_MASK\n"); 2063 dev_dbg(codec->dev, "M98090_SLD_MASK\n");
2068 }
2069 2064
2070 if (active & M98090_ULK_MASK) { 2065 if (active & M98090_ULK_MASK)
2071 dev_err(codec->dev, "M98090_ULK_MASK\n"); 2066 dev_err(codec->dev, "M98090_ULK_MASK\n");
2072 }
2073 2067
2074 if (active & M98090_JDET_MASK) { 2068 if (active & M98090_JDET_MASK) {
2075 dev_dbg(codec->dev, "M98090_JDET_MASK\n"); 2069 dev_dbg(codec->dev, "M98090_JDET_MASK\n");
@@ -2080,13 +2074,11 @@ static irqreturn_t max98090_interrupt(int irq, void *data)
2080 msecs_to_jiffies(100)); 2074 msecs_to_jiffies(100));
2081 } 2075 }
2082 2076
2083 if (active & M98090_DRCACT_MASK) { 2077 if (active & M98090_DRCACT_MASK)
2084 dev_dbg(codec->dev, "M98090_DRCACT_MASK\n"); 2078 dev_dbg(codec->dev, "M98090_DRCACT_MASK\n");
2085 }
2086 2079
2087 if (active & M98090_DRCCLP_MASK) { 2080 if (active & M98090_DRCCLP_MASK)
2088 dev_err(codec->dev, "M98090_DRCCLP_MASK\n"); 2081 dev_err(codec->dev, "M98090_DRCCLP_MASK\n");
2089 }
2090 2082
2091 return IRQ_HANDLED; 2083 return IRQ_HANDLED;
2092} 2084}
@@ -2324,7 +2316,7 @@ static int max98090_i2c_probe(struct i2c_client *i2c,
2324 max98090->pdata = i2c->dev.platform_data; 2316 max98090->pdata = i2c->dev.platform_data;
2325 max98090->irq = i2c->irq; 2317 max98090->irq = i2c->irq;
2326 2318
2327 max98090->regmap = regmap_init_i2c(i2c, &max98090_regmap); 2319 max98090->regmap = devm_regmap_init_i2c(i2c, &max98090_regmap);
2328 if (IS_ERR(max98090->regmap)) { 2320 if (IS_ERR(max98090->regmap)) {
2329 ret = PTR_ERR(max98090->regmap); 2321 ret = PTR_ERR(max98090->regmap);
2330 dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret); 2322 dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
@@ -2334,18 +2326,13 @@ static int max98090_i2c_probe(struct i2c_client *i2c,
2334 ret = snd_soc_register_codec(&i2c->dev, 2326 ret = snd_soc_register_codec(&i2c->dev,
2335 &soc_codec_dev_max98090, max98090_dai, 2327 &soc_codec_dev_max98090, max98090_dai,
2336 ARRAY_SIZE(max98090_dai)); 2328 ARRAY_SIZE(max98090_dai));
2337 if (ret < 0)
2338 regmap_exit(max98090->regmap);
2339
2340err_enable: 2329err_enable:
2341 return ret; 2330 return ret;
2342} 2331}
2343 2332
2344static int max98090_i2c_remove(struct i2c_client *client) 2333static int max98090_i2c_remove(struct i2c_client *client)
2345{ 2334{
2346 struct max98090_priv *max98090 = dev_get_drvdata(&client->dev);
2347 snd_soc_unregister_codec(&client->dev); 2335 snd_soc_unregister_codec(&client->dev);
2348 regmap_exit(max98090->regmap);
2349 return 0; 2336 return 0;
2350} 2337}
2351 2338
@@ -2369,7 +2356,7 @@ static int max98090_runtime_suspend(struct device *dev)
2369 return 0; 2356 return 0;
2370} 2357}
2371 2358
2372static struct dev_pm_ops max98090_pm = { 2359static const struct dev_pm_ops max98090_pm = {
2373 SET_RUNTIME_PM_OPS(max98090_runtime_suspend, 2360 SET_RUNTIME_PM_OPS(max98090_runtime_suspend,
2374 max98090_runtime_resume, NULL) 2361 max98090_runtime_resume, NULL)
2375}; 2362};
diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c
index 566ea3256e2d..721587c9cd84 100644
--- a/sound/soc/codecs/si476x.c
+++ b/sound/soc/codecs/si476x.c
@@ -1,3 +1,22 @@
1/*
2 * sound/soc/codecs/si476x.c -- Codec driver for SI476X chips
3 *
4 * Copyright (C) 2012 Innovative Converged Devices(ICD)
5 * Copyright (C) 2013 Andrey Smirnov
6 *
7 * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2 of the License.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 */
19
1#include <linux/module.h> 20#include <linux/module.h>
2#include <linux/slab.h> 21#include <linux/slab.h>
3#include <sound/pcm.h> 22#include <sound/pcm.h>
@@ -45,13 +64,23 @@ static unsigned int si476x_codec_read(struct snd_soc_codec *codec,
45 unsigned int reg) 64 unsigned int reg)
46{ 65{
47 int err; 66 int err;
67 unsigned int val;
48 struct si476x_core *core = codec->control_data; 68 struct si476x_core *core = codec->control_data;
49 69
50 si476x_core_lock(core); 70 si476x_core_lock(core);
51 err = si476x_core_cmd_get_property(core, reg); 71 if (!si476x_core_is_powered_up(core))
72 regcache_cache_only(core->regmap, true);
73
74 err = regmap_read(core->regmap, reg, &val);
75
76 if (!si476x_core_is_powered_up(core))
77 regcache_cache_only(core->regmap, false);
52 si476x_core_unlock(core); 78 si476x_core_unlock(core);
53 79
54 return err; 80 if (err < 0)
81 return err;
82
83 return val;
55} 84}
56 85
57static int si476x_codec_write(struct snd_soc_codec *codec, 86static int si476x_codec_write(struct snd_soc_codec *codec,
@@ -61,7 +90,13 @@ static int si476x_codec_write(struct snd_soc_codec *codec,
61 struct si476x_core *core = codec->control_data; 90 struct si476x_core *core = codec->control_data;
62 91
63 si476x_core_lock(core); 92 si476x_core_lock(core);
64 err = si476x_core_cmd_set_property(core, reg, val); 93 if (!si476x_core_is_powered_up(core))
94 regcache_cache_only(core->regmap, true);
95
96 err = regmap_write(core->regmap, reg, val);
97
98 if (!si476x_core_is_powered_up(core))
99 regcache_cache_only(core->regmap, false);
65 si476x_core_unlock(core); 100 si476x_core_unlock(core);
66 101
67 return err; 102 return err;
@@ -140,7 +175,7 @@ static int si476x_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
140 dev_err(codec_dai->codec->dev, "Failed to set output format\n"); 175 dev_err(codec_dai->codec->dev, "Failed to set output format\n");
141 return err; 176 return err;
142 } 177 }
143 178
144 return 0; 179 return 0;
145} 180}
146 181
@@ -182,7 +217,7 @@ static int si476x_codec_hw_params(struct snd_pcm_substream *substream,
182 217
183 err = snd_soc_update_bits(dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT, 218 err = snd_soc_update_bits(dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT,
184 SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK, 219 SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK,
185 (width << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) | 220 (width << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) |
186 (width << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT)); 221 (width << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT));
187 if (err < 0) { 222 if (err < 0) {
188 dev_err(dai->codec->dev, "Failed to set output width\n"); 223 dev_err(dai->codec->dev, "Failed to set output width\n");
@@ -251,6 +286,6 @@ static struct platform_driver si476x_platform_driver = {
251}; 286};
252module_platform_driver(si476x_platform_driver); 287module_platform_driver(si476x_platform_driver);
253 288
254MODULE_AUTHOR("Andrey Smirnov <andrey.smirnov@convergeddevices.net>"); 289MODULE_AUTHOR("Andrey Smirnov <andrew.smirnov@gmail.com>");
255MODULE_DESCRIPTION("ASoC Si4761/64 codec driver"); 290MODULE_DESCRIPTION("ASoC Si4761/64 codec driver");
256MODULE_LICENSE("GPL"); 291MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c
new file mode 100644
index 000000000000..d447c4aa1d5e
--- /dev/null
+++ b/sound/soc/codecs/tas5086.c
@@ -0,0 +1,591 @@
1/*
2 * TAS5086 ASoC codec driver
3 *
4 * Copyright (c) 2013 Daniel Mack <zonque@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * TODO:
17 * - implement DAPM and input muxing
18 * - implement modulation limit
19 * - implement non-default PWM start
20 *
21 * Note that this chip has a very unusual register layout, specifically
22 * because the registers are of unequal size, and multi-byte registers
23 * require bulk writes to take effect. Regmap does not support that kind
24 * of devices.
25 *
26 * Currently, the driver does not touch any of the registers >= 0x20, so
27 * it doesn't matter because the entire map can be accessed as 8-bit
28 * array. In case more features will be added in the future
29 * that require access to higher registers, the entire regmap H/W I/O
30 * routines have to be open-coded.
31 */
32
33#include <linux/module.h>
34#include <linux/slab.h>
35#include <linux/delay.h>
36#include <linux/gpio.h>
37#include <linux/i2c.h>
38#include <linux/regmap.h>
39#include <linux/spi/spi.h>
40#include <linux/of_device.h>
41#include <linux/of_gpio.h>
42#include <sound/pcm.h>
43#include <sound/pcm_params.h>
44#include <sound/soc.h>
45#include <sound/tlv.h>
46#include <sound/tas5086.h>
47
48#define TAS5086_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
49 SNDRV_PCM_FMTBIT_S20_3LE | \
50 SNDRV_PCM_FMTBIT_S24_3LE)
51
52#define TAS5086_PCM_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
53 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | \
54 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | \
55 SNDRV_PCM_RATE_192000)
56
57/*
58 * TAS5086 registers
59 */
60#define TAS5086_CLOCK_CONTROL 0x00 /* Clock control register */
61#define TAS5086_CLOCK_RATE(val) (val << 5)
62#define TAS5086_CLOCK_RATE_MASK (0x7 << 5)
63#define TAS5086_CLOCK_RATIO(val) (val << 2)
64#define TAS5086_CLOCK_RATIO_MASK (0x7 << 2)
65#define TAS5086_CLOCK_SCLK_RATIO_48 (1 << 1)
66#define TAS5086_CLOCK_VALID (1 << 0)
67
68#define TAS5086_DEEMPH_MASK 0x03
69#define TAS5086_SOFT_MUTE_ALL 0x3f
70
71#define TAS5086_DEV_ID 0x01 /* Device ID register */
72#define TAS5086_ERROR_STATUS 0x02 /* Error status register */
73#define TAS5086_SYS_CONTROL_1 0x03 /* System control register 1 */
74#define TAS5086_SERIAL_DATA_IF 0x04 /* Serial data interface register */
75#define TAS5086_SYS_CONTROL_2 0x05 /* System control register 2 */
76#define TAS5086_SOFT_MUTE 0x06 /* Soft mute register */
77#define TAS5086_MASTER_VOL 0x07 /* Master volume */
78#define TAS5086_CHANNEL_VOL(X) (0x08 + (X)) /* Channel 1-6 volume */
79#define TAS5086_VOLUME_CONTROL 0x09 /* Volume control register */
80#define TAS5086_MOD_LIMIT 0x10 /* Modulation limit register */
81#define TAS5086_PWM_START 0x18 /* PWM start register */
82#define TAS5086_SURROUND 0x19 /* Surround register */
83#define TAS5086_SPLIT_CAP_CHARGE 0x1a /* Split cap charge period register */
84#define TAS5086_OSC_TRIM 0x1b /* Oscillator trim register */
85#define TAS5086_BKNDERR 0x1c
86
87/*
88 * Default TAS5086 power-up configuration
89 */
90static const struct reg_default tas5086_reg_defaults[] = {
91 { 0x00, 0x6c },
92 { 0x01, 0x03 },
93 { 0x02, 0x00 },
94 { 0x03, 0xa0 },
95 { 0x04, 0x05 },
96 { 0x05, 0x60 },
97 { 0x06, 0x00 },
98 { 0x07, 0xff },
99 { 0x08, 0x30 },
100 { 0x09, 0x30 },
101 { 0x0a, 0x30 },
102 { 0x0b, 0x30 },
103 { 0x0c, 0x30 },
104 { 0x0d, 0x30 },
105 { 0x0e, 0xb1 },
106 { 0x0f, 0x00 },
107 { 0x10, 0x02 },
108 { 0x11, 0x00 },
109 { 0x12, 0x00 },
110 { 0x13, 0x00 },
111 { 0x14, 0x00 },
112 { 0x15, 0x00 },
113 { 0x16, 0x00 },
114 { 0x17, 0x00 },
115 { 0x18, 0x3f },
116 { 0x19, 0x00 },
117 { 0x1a, 0x18 },
118 { 0x1b, 0x82 },
119 { 0x1c, 0x05 },
120};
121
122static bool tas5086_accessible_reg(struct device *dev, unsigned int reg)
123{
124 return !((reg == 0x0f) || (reg >= 0x11 && reg <= 0x17));
125}
126
127static bool tas5086_volatile_reg(struct device *dev, unsigned int reg)
128{
129 switch (reg) {
130 case TAS5086_DEV_ID:
131 case TAS5086_ERROR_STATUS:
132 return true;
133 }
134
135 return false;
136}
137
138static bool tas5086_writeable_reg(struct device *dev, unsigned int reg)
139{
140 return tas5086_accessible_reg(dev, reg) && (reg != TAS5086_DEV_ID);
141}
142
143struct tas5086_private {
144 struct regmap *regmap;
145 unsigned int mclk, sclk;
146 unsigned int format;
147 bool deemph;
148 /* Current sample rate for de-emphasis control */
149 int rate;
150 /* GPIO driving Reset pin, if any */
151 int gpio_nreset;
152};
153
154static int tas5086_deemph[] = { 0, 32000, 44100, 48000 };
155
156static int tas5086_set_deemph(struct snd_soc_codec *codec)
157{
158 struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
159 int i, val = 0;
160
161 if (priv->deemph)
162 for (i = 0; i < ARRAY_SIZE(tas5086_deemph); i++)
163 if (tas5086_deemph[i] == priv->rate)
164 val = i;
165
166 return regmap_update_bits(priv->regmap, TAS5086_SYS_CONTROL_1,
167 TAS5086_DEEMPH_MASK, val);
168}
169
170static int tas5086_get_deemph(struct snd_kcontrol *kcontrol,
171 struct snd_ctl_elem_value *ucontrol)
172{
173 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
174 struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
175
176 ucontrol->value.enumerated.item[0] = priv->deemph;
177
178 return 0;
179}
180
181static int tas5086_put_deemph(struct snd_kcontrol *kcontrol,
182 struct snd_ctl_elem_value *ucontrol)
183{
184 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
185 struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
186
187 priv->deemph = ucontrol->value.enumerated.item[0];
188
189 return tas5086_set_deemph(codec);
190}
191
192
193static int tas5086_set_dai_sysclk(struct snd_soc_dai *codec_dai,
194 int clk_id, unsigned int freq, int dir)
195{
196 struct snd_soc_codec *codec = codec_dai->codec;
197 struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
198
199 switch (clk_id) {
200 case TAS5086_CLK_IDX_MCLK:
201 priv->mclk = freq;
202 break;
203 case TAS5086_CLK_IDX_SCLK:
204 priv->sclk = freq;
205 break;
206 }
207
208 return 0;
209}
210
211static int tas5086_set_dai_fmt(struct snd_soc_dai *codec_dai,
212 unsigned int format)
213{
214 struct snd_soc_codec *codec = codec_dai->codec;
215 struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
216
217 /* The TAS5086 can only be slave to all clocks */
218 if ((format & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
219 dev_err(codec->dev, "Invalid clocking mode\n");
220 return -EINVAL;
221 }
222
223 /* we need to refer to the data format from hw_params() */
224 priv->format = format;
225
226 return 0;
227}
228
229static const int tas5086_sample_rates[] = {
230 32000, 38000, 44100, 48000, 88200, 96000, 176400, 192000
231};
232
233static const int tas5086_ratios[] = {
234 64, 128, 192, 256, 384, 512
235};
236
237static int index_in_array(const int *array, int len, int needle)
238{
239 int i;
240
241 for (i = 0; i < len; i++)
242 if (array[i] == needle)
243 return i;
244
245 return -ENOENT;
246}
247
248static int tas5086_hw_params(struct snd_pcm_substream *substream,
249 struct snd_pcm_hw_params *params,
250 struct snd_soc_dai *dai)
251{
252 struct snd_soc_codec *codec = dai->codec;
253 struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
254 int val;
255 int ret;
256
257 priv->rate = params_rate(params);
258
259 /* Look up the sample rate and refer to the offset in the list */
260 val = index_in_array(tas5086_sample_rates,
261 ARRAY_SIZE(tas5086_sample_rates), priv->rate);
262
263 if (val < 0) {
264 dev_err(codec->dev, "Invalid sample rate\n");
265 return -EINVAL;
266 }
267
268 ret = regmap_update_bits(priv->regmap, TAS5086_CLOCK_CONTROL,
269 TAS5086_CLOCK_RATE_MASK,
270 TAS5086_CLOCK_RATE(val));
271 if (ret < 0)
272 return ret;
273
274 /* MCLK / Fs ratio */
275 val = index_in_array(tas5086_ratios, ARRAY_SIZE(tas5086_ratios),
276 priv->mclk / priv->rate);
277 if (val < 0) {
278 dev_err(codec->dev, "Inavlid MCLK / Fs ratio\n");
279 return -EINVAL;
280 }
281
282 ret = regmap_update_bits(priv->regmap, TAS5086_CLOCK_CONTROL,
283 TAS5086_CLOCK_RATIO_MASK,
284 TAS5086_CLOCK_RATIO(val));
285 if (ret < 0)
286 return ret;
287
288
289 ret = regmap_update_bits(priv->regmap, TAS5086_CLOCK_CONTROL,
290 TAS5086_CLOCK_SCLK_RATIO_48,
291 (priv->sclk == 48 * priv->rate) ?
292 TAS5086_CLOCK_SCLK_RATIO_48 : 0);
293 if (ret < 0)
294 return ret;
295
296 /*
297 * The chip has a very unituitive register mapping and muxes information
298 * about data format and sample depth into the same register, but not on
299 * a logical bit-boundary. Hence, we have to refer to the format passed
300 * in the set_dai_fmt() callback and set up everything from here.
301 *
302 * First, determine the 'base' value, using the format ...
303 */
304 switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) {
305 case SND_SOC_DAIFMT_RIGHT_J:
306 val = 0x00;
307 break;
308 case SND_SOC_DAIFMT_I2S:
309 val = 0x03;
310 break;
311 case SND_SOC_DAIFMT_LEFT_J:
312 val = 0x06;
313 break;
314 default:
315 dev_err(codec->dev, "Invalid DAI format\n");
316 return -EINVAL;
317 }
318
319 /* ... then add the offset for the sample bit depth. */
320 switch (params_format(params)) {
321 case SNDRV_PCM_FORMAT_S16_LE:
322 val += 0;
323 break;
324 case SNDRV_PCM_FORMAT_S20_3LE:
325 val += 1;
326 break;
327 case SNDRV_PCM_FORMAT_S24_3LE:
328 val += 2;
329 break;
330 default:
331 dev_err(codec->dev, "Invalid bit width\n");
332 return -EINVAL;
333 };
334
335 ret = regmap_write(priv->regmap, TAS5086_SERIAL_DATA_IF, val);
336 if (ret < 0)
337 return ret;
338
339 /* clock is considered valid now */
340 ret = regmap_update_bits(priv->regmap, TAS5086_CLOCK_CONTROL,
341 TAS5086_CLOCK_VALID, TAS5086_CLOCK_VALID);
342 if (ret < 0)
343 return ret;
344
345 return tas5086_set_deemph(codec);
346}
347
348static int tas5086_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
349{
350 struct snd_soc_codec *codec = dai->codec;
351 struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
352 unsigned int val = 0;
353
354 if (mute)
355 val = TAS5086_SOFT_MUTE_ALL;
356
357 return regmap_write(priv->regmap, TAS5086_SOFT_MUTE, val);
358}
359
360/* TAS5086 controls */
361static const DECLARE_TLV_DB_SCALE(tas5086_dac_tlv, -10350, 50, 1);
362
363static const struct snd_kcontrol_new tas5086_controls[] = {
364 SOC_SINGLE_TLV("Master Playback Volume", TAS5086_MASTER_VOL,
365 0, 0xff, 1, tas5086_dac_tlv),
366 SOC_DOUBLE_R_TLV("Channel 1/2 Playback Volume",
367 TAS5086_CHANNEL_VOL(0), TAS5086_CHANNEL_VOL(1),
368 0, 0xff, 1, tas5086_dac_tlv),
369 SOC_DOUBLE_R_TLV("Channel 3/4 Playback Volume",
370 TAS5086_CHANNEL_VOL(2), TAS5086_CHANNEL_VOL(3),
371 0, 0xff, 1, tas5086_dac_tlv),
372 SOC_DOUBLE_R_TLV("Channel 5/6 Playback Volume",
373 TAS5086_CHANNEL_VOL(4), TAS5086_CHANNEL_VOL(5),
374 0, 0xff, 1, tas5086_dac_tlv),
375 SOC_SINGLE_BOOL_EXT("De-emphasis Switch", 0,
376 tas5086_get_deemph, tas5086_put_deemph),
377};
378
379static const struct snd_soc_dai_ops tas5086_dai_ops = {
380 .hw_params = tas5086_hw_params,
381 .set_sysclk = tas5086_set_dai_sysclk,
382 .set_fmt = tas5086_set_dai_fmt,
383 .mute_stream = tas5086_mute_stream,
384};
385
386static struct snd_soc_dai_driver tas5086_dai = {
387 .name = "tas5086-hifi",
388 .playback = {
389 .stream_name = "Playback",
390 .channels_min = 2,
391 .channels_max = 6,
392 .rates = TAS5086_PCM_RATES,
393 .formats = TAS5086_PCM_FORMATS,
394 },
395 .ops = &tas5086_dai_ops,
396};
397
398#ifdef CONFIG_PM
399static int tas5086_soc_resume(struct snd_soc_codec *codec)
400{
401 struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
402
403 /* Restore codec state */
404 return regcache_sync(priv->regmap);
405}
406#else
407#define tas5086_soc_resume NULL
408#endif /* CONFIG_PM */
409
410#ifdef CONFIG_OF
411static const struct of_device_id tas5086_dt_ids[] = {
412 { .compatible = "ti,tas5086", },
413 { }
414};
415MODULE_DEVICE_TABLE(of, tas5086_dt_ids);
416#endif
417
418/* charge period values in microseconds */
419static const int tas5086_charge_period[] = {
420 13000, 16900, 23400, 31200, 41600, 54600, 72800, 96200,
421 130000, 156000, 234000, 312000, 416000, 546000, 728000, 962000,
422 1300000, 169000, 2340000, 3120000, 4160000, 5460000, 7280000, 9620000,
423};
424
425static int tas5086_probe(struct snd_soc_codec *codec)
426{
427 struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
428 int charge_period = 1300000; /* hardware default is 1300 ms */
429 int i, ret;
430
431 if (of_match_device(of_match_ptr(tas5086_dt_ids), codec->dev)) {
432 struct device_node *of_node = codec->dev->of_node;
433 of_property_read_u32(of_node, "ti,charge-period", &charge_period);
434 }
435
436 /* lookup and set split-capacitor charge period */
437 if (charge_period == 0) {
438 regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE, 0);
439 } else {
440 i = index_in_array(tas5086_charge_period,
441 ARRAY_SIZE(tas5086_charge_period),
442 charge_period);
443 if (i >= 0)
444 regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE,
445 i + 0x08);
446 else
447 dev_warn(codec->dev,
448 "Invalid split-cap charge period of %d ns.\n",
449 charge_period);
450 }
451
452 /* enable factory trim */
453 ret = regmap_write(priv->regmap, TAS5086_OSC_TRIM, 0x00);
454 if (ret < 0)
455 return ret;
456
457 /* start all channels */
458 ret = regmap_write(priv->regmap, TAS5086_SYS_CONTROL_2, 0x20);
459 if (ret < 0)
460 return ret;
461
462 /* set master volume to 0 dB */
463 ret = regmap_write(priv->regmap, TAS5086_MASTER_VOL, 0x30);
464 if (ret < 0)
465 return ret;
466
467 /* mute all channels for now */
468 ret = regmap_write(priv->regmap, TAS5086_SOFT_MUTE,
469 TAS5086_SOFT_MUTE_ALL);
470 if (ret < 0)
471 return ret;
472
473 return 0;
474}
475
476static int tas5086_remove(struct snd_soc_codec *codec)
477{
478 struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
479
480 if (gpio_is_valid(priv->gpio_nreset))
481 /* Set codec to the reset state */
482 gpio_set_value(priv->gpio_nreset, 0);
483
484 return 0;
485};
486
487static struct snd_soc_codec_driver soc_codec_dev_tas5086 = {
488 .probe = tas5086_probe,
489 .remove = tas5086_remove,
490 .resume = tas5086_soc_resume,
491 .controls = tas5086_controls,
492 .num_controls = ARRAY_SIZE(tas5086_controls),
493};
494
495static const struct i2c_device_id tas5086_i2c_id[] = {
496 { "tas5086", 0 },
497 { }
498};
499MODULE_DEVICE_TABLE(i2c, tas5086_i2c_id);
500
501static const struct regmap_config tas5086_regmap = {
502 .reg_bits = 8,
503 .val_bits = 8,
504 .max_register = ARRAY_SIZE(tas5086_reg_defaults),
505 .reg_defaults = tas5086_reg_defaults,
506 .num_reg_defaults = ARRAY_SIZE(tas5086_reg_defaults),
507 .cache_type = REGCACHE_RBTREE,
508 .volatile_reg = tas5086_volatile_reg,
509 .writeable_reg = tas5086_writeable_reg,
510 .readable_reg = tas5086_accessible_reg,
511};
512
513static int tas5086_i2c_probe(struct i2c_client *i2c,
514 const struct i2c_device_id *id)
515{
516 struct tas5086_private *priv;
517 struct device *dev = &i2c->dev;
518 int gpio_nreset = -EINVAL;
519 int i, ret;
520
521 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
522 if (!priv)
523 return -ENOMEM;
524
525 priv->regmap = devm_regmap_init_i2c(i2c, &tas5086_regmap);
526 if (IS_ERR(priv->regmap)) {
527 ret = PTR_ERR(priv->regmap);
528 dev_err(&i2c->dev, "Failed to create regmap: %d\n", ret);
529 return ret;
530 }
531
532 i2c_set_clientdata(i2c, priv);
533
534 if (of_match_device(of_match_ptr(tas5086_dt_ids), dev)) {
535 struct device_node *of_node = dev->of_node;
536 gpio_nreset = of_get_named_gpio(of_node, "reset-gpio", 0);
537 }
538
539 if (gpio_is_valid(gpio_nreset))
540 if (devm_gpio_request(dev, gpio_nreset, "TAS5086 Reset"))
541 gpio_nreset = -EINVAL;
542
543 if (gpio_is_valid(gpio_nreset)) {
544 /* Reset codec - minimum assertion time is 400ns */
545 gpio_direction_output(gpio_nreset, 0);
546 udelay(1);
547 gpio_set_value(gpio_nreset, 1);
548
549 /* Codec needs ~15ms to wake up */
550 msleep(15);
551 }
552
553 priv->gpio_nreset = gpio_nreset;
554
555 /* The TAS5086 always returns 0x03 in its TAS5086_DEV_ID register */
556 ret = regmap_read(priv->regmap, TAS5086_DEV_ID, &i);
557 if (ret < 0)
558 return ret;
559
560 if (i != 0x3) {
561 dev_err(dev,
562 "Failed to identify TAS5086 codec (got %02x)\n", i);
563 return -ENODEV;
564 }
565
566 return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_tas5086,
567 &tas5086_dai, 1);
568}
569
570static int tas5086_i2c_remove(struct i2c_client *i2c)
571{
572 snd_soc_unregister_codec(&i2c->dev);
573 return 0;
574}
575
576static struct i2c_driver tas5086_i2c_driver = {
577 .driver = {
578 .name = "tas5086",
579 .owner = THIS_MODULE,
580 .of_match_table = of_match_ptr(tas5086_dt_ids),
581 },
582 .id_table = tas5086_i2c_id,
583 .probe = tas5086_i2c_probe,
584 .remove = tas5086_i2c_remove,
585};
586
587module_i2c_driver(tas5086_i2c_driver);
588
589MODULE_AUTHOR("Daniel Mack <zonque@gmail.com>");
590MODULE_DESCRIPTION("Texas Instruments TAS5086 ALSA SoC Codec Driver");
591MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c
index ad2fee4bb4cd..8df2b6e1a1a6 100644
--- a/sound/soc/codecs/wm0010.c
+++ b/sound/soc/codecs/wm0010.c
@@ -342,7 +342,7 @@ static void byte_swap_64(u64 *data_in, u64 *data_out, u32 len)
342 data_out[i] = cpu_to_be64(le64_to_cpu(data_in[i])); 342 data_out[i] = cpu_to_be64(le64_to_cpu(data_in[i]));
343} 343}
344 344
345static int wm0010_firmware_load(char *name, struct snd_soc_codec *codec) 345static int wm0010_firmware_load(const char *name, struct snd_soc_codec *codec)
346{ 346{
347 struct spi_device *spi = to_spi_device(codec->dev); 347 struct spi_device *spi = to_spi_device(codec->dev);
348 struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); 348 struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec);
@@ -361,8 +361,8 @@ static int wm0010_firmware_load(char *name, struct snd_soc_codec *codec)
361 361
362 ret = request_firmware(&fw, name, codec->dev); 362 ret = request_firmware(&fw, name, codec->dev);
363 if (ret != 0) { 363 if (ret != 0) {
364 dev_err(codec->dev, "Failed to request application: %d\n", 364 dev_err(codec->dev, "Failed to request application(%s): %d\n",
365 ret); 365 name, ret);
366 return ret; 366 return ret;
367 } 367 }
368 368
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c
index f2ac38b61a1b..7fefd766b582 100644
--- a/sound/soc/codecs/wm2000.c
+++ b/sound/soc/codecs/wm2000.c
@@ -761,6 +761,8 @@ static bool wm2000_readable_reg(struct device *dev, unsigned int reg)
761 case WM2000_REG_SYS_CTL2: 761 case WM2000_REG_SYS_CTL2:
762 case WM2000_REG_ANC_STAT: 762 case WM2000_REG_ANC_STAT:
763 case WM2000_REG_IF_CTL: 763 case WM2000_REG_IF_CTL:
764 case WM2000_REG_ANA_MIC_CTL:
765 case WM2000_REG_SPK_CTL:
764 return true; 766 return true;
765 default: 767 default:
766 return false; 768 return false;
@@ -771,7 +773,7 @@ static const struct regmap_config wm2000_regmap = {
771 .reg_bits = 16, 773 .reg_bits = 16,
772 .val_bits = 8, 774 .val_bits = 8,
773 775
774 .max_register = WM2000_REG_IF_CTL, 776 .max_register = WM2000_REG_SPK_CTL,
775 .readable_reg = wm2000_readable_reg, 777 .readable_reg = wm2000_readable_reg,
776}; 778};
777 779
diff --git a/sound/soc/codecs/wm2000.h b/sound/soc/codecs/wm2000.h
index fb812cd9e77d..3870c0e1d246 100644
--- a/sound/soc/codecs/wm2000.h
+++ b/sound/soc/codecs/wm2000.h
@@ -30,6 +30,8 @@
30#define WM2000_REG_SYS_CTL2 0xf004 30#define WM2000_REG_SYS_CTL2 0xf004
31#define WM2000_REG_ANC_STAT 0xf005 31#define WM2000_REG_ANC_STAT 0xf005
32#define WM2000_REG_IF_CTL 0xf006 32#define WM2000_REG_IF_CTL 0xf006
33#define WM2000_REG_ANA_MIC_CTL 0xf028
34#define WM2000_REG_SPK_CTL 0xf034
33 35
34/* SPEECH_CLARITY */ 36/* SPEECH_CLARITY */
35#define WM2000_SPEECH_CLARITY 0x01 37#define WM2000_SPEECH_CLARITY 0x01
diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c
index ddc98f02ecbd..57ba315d0c84 100644
--- a/sound/soc/codecs/wm2200.c
+++ b/sound/soc/codecs/wm2200.c
@@ -1565,7 +1565,7 @@ static int wm2200_probe(struct snd_soc_codec *codec)
1565 return ret; 1565 return ret;
1566 } 1566 }
1567 1567
1568 ret = snd_soc_add_codec_controls(codec, wm_adsp_fw_controls, 2); 1568 ret = snd_soc_add_codec_controls(codec, wm_adsp1_fw_controls, 2);
1569 if (ret != 0) 1569 if (ret != 0)
1570 return ret; 1570 return ret;
1571 1571
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c
index 15bc31f1abb1..e895d3939eef 100644
--- a/sound/soc/codecs/wm5102.c
+++ b/sound/soc/codecs/wm5102.c
@@ -36,9 +36,6 @@
36struct wm5102_priv { 36struct wm5102_priv {
37 struct arizona_priv core; 37 struct arizona_priv core;
38 struct arizona_fll fll[2]; 38 struct arizona_fll fll[2];
39
40 unsigned int spk_ena:2;
41 unsigned int spk_ena_pending:1;
42}; 39};
43 40
44static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); 41static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0);
@@ -615,6 +612,26 @@ static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w,
615 return 0; 612 return 0;
616} 613}
617 614
615static const char *wm5102_osr_text[] = {
616 "Low power", "Normal", "High performance",
617};
618
619static const unsigned int wm5102_osr_val[] = {
620 0x0, 0x3, 0x5,
621};
622
623static const struct soc_enum wm5102_hpout_osr[] = {
624 SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1L,
625 ARIZONA_OUT1_OSR_SHIFT, 0x7, 3,
626 wm5102_osr_text, wm5102_osr_val),
627 SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_2L,
628 ARIZONA_OUT2_OSR_SHIFT, 0x7, 3,
629 wm5102_osr_text, wm5102_osr_val),
630 SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_3L,
631 ARIZONA_OUT3_OSR_SHIFT, 0x7, 3,
632 wm5102_osr_text, wm5102_osr_val),
633};
634
618#define WM5102_NG_SRC(name, base) \ 635#define WM5102_NG_SRC(name, base) \
619 SOC_SINGLE(name " NG HPOUT1L Switch", base, 0, 1, 0), \ 636 SOC_SINGLE(name " NG HPOUT1L Switch", base, 0, 1, 0), \
620 SOC_SINGLE(name " NG HPOUT1R Switch", base, 1, 1, 0), \ 637 SOC_SINGLE(name " NG HPOUT1R Switch", base, 1, 1, 0), \
@@ -745,6 +762,9 @@ SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
745SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode), 762SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
746SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode), 763SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode),
747 764
765SOC_VALUE_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]),
766SOC_VALUE_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]),
767
748ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE), 768ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE),
749ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE), 769ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE),
750 770
@@ -761,6 +781,8 @@ ARIZONA_MIXER_CONTROLS("SPKOUTR", ARIZONA_OUT4RMIX_INPUT_1_SOURCE),
761ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE), 781ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE),
762ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE), 782ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE),
763 783
784SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L,
785 ARIZONA_OUT4_OSR_SHIFT, 1, 0),
764SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L, 786SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L,
765 ARIZONA_OUT5_OSR_SHIFT, 1, 0), 787 ARIZONA_OUT5_OSR_SHIFT, 1, 0),
766 788
@@ -790,6 +812,10 @@ SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L,
790 ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT, 812 ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT,
791 0xbf, 0, digital_tlv), 813 0xbf, 0, digital_tlv),
792 814
815SOC_VALUE_ENUM("HPOUT1 OSR", wm5102_hpout_osr[0]),
816SOC_VALUE_ENUM("HPOUT2 OSR", wm5102_hpout_osr[1]),
817SOC_VALUE_ENUM("HPOUT3 OSR", wm5102_hpout_osr[2]),
818
793SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp), 819SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp),
794SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp), 820SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp),
795 821
@@ -828,47 +854,6 @@ ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE),
828ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE), 854ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE),
829}; 855};
830 856
831static int wm5102_spk_ev(struct snd_soc_dapm_widget *w,
832 struct snd_kcontrol *kcontrol,
833 int event)
834{
835 struct snd_soc_codec *codec = w->codec;
836 struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
837 struct wm5102_priv *wm5102 = snd_soc_codec_get_drvdata(codec);
838
839 if (arizona->rev < 1)
840 return 0;
841
842 switch (event) {
843 case SND_SOC_DAPM_PRE_PMU:
844 if (!wm5102->spk_ena) {
845 snd_soc_write(codec, 0x4f5, 0x25a);
846 wm5102->spk_ena_pending = true;
847 }
848 break;
849 case SND_SOC_DAPM_POST_PMU:
850 if (wm5102->spk_ena_pending) {
851 msleep(75);
852 snd_soc_write(codec, 0x4f5, 0xda);
853 wm5102->spk_ena_pending = false;
854 wm5102->spk_ena++;
855 }
856 break;
857 case SND_SOC_DAPM_PRE_PMD:
858 wm5102->spk_ena--;
859 if (!wm5102->spk_ena)
860 snd_soc_write(codec, 0x4f5, 0x25a);
861 break;
862 case SND_SOC_DAPM_POST_PMD:
863 if (!wm5102->spk_ena)
864 snd_soc_write(codec, 0x4f5, 0x0da);
865 break;
866 }
867
868 return 0;
869}
870
871
872ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE); 857ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE);
873ARIZONA_MIXER_ENUMS(EQ2, ARIZONA_EQ2MIX_INPUT_1_SOURCE); 858ARIZONA_MIXER_ENUMS(EQ2, ARIZONA_EQ2MIX_INPUT_1_SOURCE);
874ARIZONA_MIXER_ENUMS(EQ3, ARIZONA_EQ3MIX_INPUT_1_SOURCE); 859ARIZONA_MIXER_ENUMS(EQ3, ARIZONA_EQ3MIX_INPUT_1_SOURCE);
@@ -984,22 +969,28 @@ SND_SOC_DAPM_INPUT("IN3R"),
984 969
985SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT, 970SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT,
986 0, NULL, 0, arizona_in_ev, 971 0, NULL, 0, arizona_in_ev,
987 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), 972 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
973 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
988SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT, 974SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT,
989 0, NULL, 0, arizona_in_ev, 975 0, NULL, 0, arizona_in_ev,
990 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), 976 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
977 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
991SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT, 978SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT,
992 0, NULL, 0, arizona_in_ev, 979 0, NULL, 0, arizona_in_ev,
993 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), 980 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
981 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
994SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT, 982SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT,
995 0, NULL, 0, arizona_in_ev, 983 0, NULL, 0, arizona_in_ev,
996 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), 984 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
985 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
997SND_SOC_DAPM_PGA_E("IN3L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3L_ENA_SHIFT, 986SND_SOC_DAPM_PGA_E("IN3L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3L_ENA_SHIFT,
998 0, NULL, 0, arizona_in_ev, 987 0, NULL, 0, arizona_in_ev,
999 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), 988 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
989 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
1000SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT, 990SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT,
1001 0, NULL, 0, arizona_in_ev, 991 0, NULL, 0, arizona_in_ev,
1002 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), 992 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
993 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
1003 994
1004SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1, 995SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1,
1005 ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), 996 ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
@@ -1146,12 +1137,6 @@ SND_SOC_DAPM_PGA_E("OUT2R", ARIZONA_OUTPUT_ENABLES_1,
1146SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1, 1137SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1,
1147 ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, 1138 ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
1148 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), 1139 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
1149SND_SOC_DAPM_PGA_E("OUT4L", ARIZONA_OUTPUT_ENABLES_1,
1150 ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, wm5102_spk_ev,
1151 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
1152SND_SOC_DAPM_PGA_E("OUT4R", ARIZONA_OUTPUT_ENABLES_1,
1153 ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, wm5102_spk_ev,
1154 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
1155SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1, 1140SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1,
1156 ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, 1141 ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
1157 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), 1142 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
@@ -1494,6 +1479,12 @@ static int wm5102_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
1494 return arizona_set_fll(&wm5102->fll[0], source, Fref, Fout); 1479 return arizona_set_fll(&wm5102->fll[0], source, Fref, Fout);
1495 case WM5102_FLL2: 1480 case WM5102_FLL2:
1496 return arizona_set_fll(&wm5102->fll[1], source, Fref, Fout); 1481 return arizona_set_fll(&wm5102->fll[1], source, Fref, Fout);
1482 case WM5102_FLL1_REFCLK:
1483 return arizona_set_fll_refclk(&wm5102->fll[0], source, Fref,
1484 Fout);
1485 case WM5102_FLL2_REFCLK:
1486 return arizona_set_fll_refclk(&wm5102->fll[1], source, Fref,
1487 Fout);
1497 default: 1488 default:
1498 return -EINVAL; 1489 return -EINVAL;
1499 } 1490 }
@@ -1581,10 +1572,12 @@ static int wm5102_codec_probe(struct snd_soc_codec *codec)
1581 if (ret != 0) 1572 if (ret != 0)
1582 return ret; 1573 return ret;
1583 1574
1584 ret = snd_soc_add_codec_controls(codec, wm_adsp_fw_controls, 1); 1575 ret = snd_soc_add_codec_controls(codec, wm_adsp2_fw_controls, 2);
1585 if (ret != 0) 1576 if (ret != 0)
1586 return ret; 1577 return ret;
1587 1578
1579 arizona_init_spk(codec);
1580
1588 snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS"); 1581 snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS");
1589 1582
1590 priv->core.arizona->dapm = &codec->dapm; 1583 priv->core.arizona->dapm = &codec->dapm;
@@ -1604,13 +1597,6 @@ static int wm5102_codec_remove(struct snd_soc_codec *codec)
1604#define WM5102_DIG_VU 0x0200 1597#define WM5102_DIG_VU 0x0200
1605 1598
1606static unsigned int wm5102_digital_vu[] = { 1599static unsigned int wm5102_digital_vu[] = {
1607 ARIZONA_ADC_DIGITAL_VOLUME_1L,
1608 ARIZONA_ADC_DIGITAL_VOLUME_1R,
1609 ARIZONA_ADC_DIGITAL_VOLUME_2L,
1610 ARIZONA_ADC_DIGITAL_VOLUME_2R,
1611 ARIZONA_ADC_DIGITAL_VOLUME_3L,
1612 ARIZONA_ADC_DIGITAL_VOLUME_3R,
1613
1614 ARIZONA_DAC_DIGITAL_VOLUME_1L, 1600 ARIZONA_DAC_DIGITAL_VOLUME_1L,
1615 ARIZONA_DAC_DIGITAL_VOLUME_1R, 1601 ARIZONA_DAC_DIGITAL_VOLUME_1R,
1616 ARIZONA_DAC_DIGITAL_VOLUME_2L, 1602 ARIZONA_DAC_DIGITAL_VOLUME_2L,
@@ -1653,6 +1639,7 @@ static int wm5102_probe(struct platform_device *pdev)
1653 platform_set_drvdata(pdev, wm5102); 1639 platform_set_drvdata(pdev, wm5102);
1654 1640
1655 wm5102->core.arizona = arizona; 1641 wm5102->core.arizona = arizona;
1642 wm5102->core.num_inputs = 6;
1656 1643
1657 wm5102->core.adsp[0].part = "wm5102"; 1644 wm5102->core.adsp[0].part = "wm5102";
1658 wm5102->core.adsp[0].num = 1; 1645 wm5102->core.adsp[0].num = 1;
@@ -1677,6 +1664,12 @@ static int wm5102_probe(struct platform_device *pdev)
1677 ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK, 1664 ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK,
1678 &wm5102->fll[1]); 1665 &wm5102->fll[1]);
1679 1666
1667 /* SR2 fixed at 8kHz, SR3 fixed at 16kHz */
1668 regmap_update_bits(arizona->regmap, ARIZONA_SAMPLE_RATE_2,
1669 ARIZONA_SAMPLE_RATE_2_MASK, 0x11);
1670 regmap_update_bits(arizona->regmap, ARIZONA_SAMPLE_RATE_3,
1671 ARIZONA_SAMPLE_RATE_3_MASK, 0x12);
1672
1680 for (i = 0; i < ARRAY_SIZE(wm5102_dai); i++) 1673 for (i = 0; i < ARRAY_SIZE(wm5102_dai); i++)
1681 arizona_init_dai(&wm5102->core, i); 1674 arizona_init_dai(&wm5102->core, i);
1682 1675
diff --git a/sound/soc/codecs/wm5102.h b/sound/soc/codecs/wm5102.h
index d30477f3070c..adb38040f661 100644
--- a/sound/soc/codecs/wm5102.h
+++ b/sound/soc/codecs/wm5102.h
@@ -15,7 +15,9 @@
15 15
16#include "arizona.h" 16#include "arizona.h"
17 17
18#define WM5102_FLL1 1 18#define WM5102_FLL1 1
19#define WM5102_FLL2 2 19#define WM5102_FLL2 2
20#define WM5102_FLL1_REFCLK 3
21#define WM5102_FLL2_REFCLK 4
20 22
21#endif 23#endif
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c
index 7841b42a819c..731884e04776 100644
--- a/sound/soc/codecs/wm5110.c
+++ b/sound/soc/codecs/wm5110.c
@@ -416,28 +416,36 @@ SND_SOC_DAPM_INPUT("IN4R"),
416 416
417SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT, 417SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT,
418 0, NULL, 0, arizona_in_ev, 418 0, NULL, 0, arizona_in_ev,
419 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), 419 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
420 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
420SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT, 421SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT,
421 0, NULL, 0, arizona_in_ev, 422 0, NULL, 0, arizona_in_ev,
422 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), 423 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
424 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
423SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT, 425SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT,
424 0, NULL, 0, arizona_in_ev, 426 0, NULL, 0, arizona_in_ev,
425 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), 427 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
428 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
426SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT, 429SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT,
427 0, NULL, 0, arizona_in_ev, 430 0, NULL, 0, arizona_in_ev,
428 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), 431 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
432 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
429SND_SOC_DAPM_PGA_E("IN3L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3L_ENA_SHIFT, 433SND_SOC_DAPM_PGA_E("IN3L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3L_ENA_SHIFT,
430 0, NULL, 0, arizona_in_ev, 434 0, NULL, 0, arizona_in_ev,
431 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), 435 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
436 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
432SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT, 437SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT,
433 0, NULL, 0, arizona_in_ev, 438 0, NULL, 0, arizona_in_ev,
434 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), 439 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
440 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
435SND_SOC_DAPM_PGA_E("IN4L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4L_ENA_SHIFT, 441SND_SOC_DAPM_PGA_E("IN4L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4L_ENA_SHIFT,
436 0, NULL, 0, arizona_in_ev, 442 0, NULL, 0, arizona_in_ev,
437 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), 443 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
444 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
438SND_SOC_DAPM_PGA_E("IN4R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4R_ENA_SHIFT, 445SND_SOC_DAPM_PGA_E("IN4R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4R_ENA_SHIFT,
439 0, NULL, 0, arizona_in_ev, 446 0, NULL, 0, arizona_in_ev,
440 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), 447 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
448 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
441 449
442SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1, 450SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1,
443 ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), 451 ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
@@ -569,12 +577,6 @@ SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1,
569SND_SOC_DAPM_PGA_E("OUT3R", ARIZONA_OUTPUT_ENABLES_1, 577SND_SOC_DAPM_PGA_E("OUT3R", ARIZONA_OUTPUT_ENABLES_1,
570 ARIZONA_OUT3R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, 578 ARIZONA_OUT3R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
571 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), 579 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
572SND_SOC_DAPM_PGA_E("OUT4L", ARIZONA_OUTPUT_ENABLES_1,
573 ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
574 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
575SND_SOC_DAPM_PGA_E("OUT4R", ARIZONA_OUTPUT_ENABLES_1,
576 ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
577 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
578SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1, 580SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1,
579 ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, 581 ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
580 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), 582 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
@@ -880,6 +882,12 @@ static int wm5110_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
880 return arizona_set_fll(&wm5110->fll[0], source, Fref, Fout); 882 return arizona_set_fll(&wm5110->fll[0], source, Fref, Fout);
881 case WM5110_FLL2: 883 case WM5110_FLL2:
882 return arizona_set_fll(&wm5110->fll[1], source, Fref, Fout); 884 return arizona_set_fll(&wm5110->fll[1], source, Fref, Fout);
885 case WM5110_FLL1_REFCLK:
886 return arizona_set_fll_refclk(&wm5110->fll[0], source, Fref,
887 Fout);
888 case WM5110_FLL2_REFCLK:
889 return arizona_set_fll_refclk(&wm5110->fll[1], source, Fref,
890 Fout);
883 default: 891 default:
884 return -EINVAL; 892 return -EINVAL;
885 } 893 }
@@ -987,15 +995,6 @@ static int wm5110_codec_remove(struct snd_soc_codec *codec)
987#define WM5110_DIG_VU 0x0200 995#define WM5110_DIG_VU 0x0200
988 996
989static unsigned int wm5110_digital_vu[] = { 997static unsigned int wm5110_digital_vu[] = {
990 ARIZONA_ADC_DIGITAL_VOLUME_1L,
991 ARIZONA_ADC_DIGITAL_VOLUME_1R,
992 ARIZONA_ADC_DIGITAL_VOLUME_2L,
993 ARIZONA_ADC_DIGITAL_VOLUME_2R,
994 ARIZONA_ADC_DIGITAL_VOLUME_3L,
995 ARIZONA_ADC_DIGITAL_VOLUME_3R,
996 ARIZONA_ADC_DIGITAL_VOLUME_4L,
997 ARIZONA_ADC_DIGITAL_VOLUME_4R,
998
999 ARIZONA_DAC_DIGITAL_VOLUME_1L, 998 ARIZONA_DAC_DIGITAL_VOLUME_1L,
1000 ARIZONA_DAC_DIGITAL_VOLUME_1R, 999 ARIZONA_DAC_DIGITAL_VOLUME_1R,
1001 ARIZONA_DAC_DIGITAL_VOLUME_2L, 1000 ARIZONA_DAC_DIGITAL_VOLUME_2L,
@@ -1040,6 +1039,7 @@ static int wm5110_probe(struct platform_device *pdev)
1040 platform_set_drvdata(pdev, wm5110); 1039 platform_set_drvdata(pdev, wm5110);
1041 1040
1042 wm5110->core.arizona = arizona; 1041 wm5110->core.arizona = arizona;
1042 wm5110->core.num_inputs = 8;
1043 1043
1044 for (i = 0; i < ARRAY_SIZE(wm5110->fll); i++) 1044 for (i = 0; i < ARRAY_SIZE(wm5110->fll); i++)
1045 wm5110->fll[i].vco_mult = 3; 1045 wm5110->fll[i].vco_mult = 3;
diff --git a/sound/soc/codecs/wm5110.h b/sound/soc/codecs/wm5110.h
index 75e9351ccab0..e6c0cd4235c5 100644
--- a/sound/soc/codecs/wm5110.h
+++ b/sound/soc/codecs/wm5110.h
@@ -15,7 +15,9 @@
15 15
16#include "arizona.h" 16#include "arizona.h"
17 17
18#define WM5110_FLL1 1 18#define WM5110_FLL1 1
19#define WM5110_FLL2 2 19#define WM5110_FLL2 2
20#define WM5110_FLL1_REFCLK 3
21#define WM5110_FLL2_REFCLK 4
20 22
21#endif 23#endif
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index f8a31ad0b203..9d88437cdcd1 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -478,6 +478,8 @@ static int wm8903_put_deemph(struct snd_kcontrol *kcontrol,
478/* ALSA can only do steps of .01dB */ 478/* ALSA can only do steps of .01dB */
479static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); 479static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1);
480 480
481static const DECLARE_TLV_DB_SCALE(dac_boost_tlv, 0, 600, 0);
482
481static const DECLARE_TLV_DB_SCALE(digital_sidetone_tlv, -3600, 300, 0); 483static const DECLARE_TLV_DB_SCALE(digital_sidetone_tlv, -3600, 300, 0);
482static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0); 484static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0);
483 485
@@ -698,6 +700,8 @@ SOC_ENUM("DAC Mute Mode", mute_mode),
698SOC_SINGLE("DAC Mono Switch", WM8903_DAC_DIGITAL_1, 12, 1, 0), 700SOC_SINGLE("DAC Mono Switch", WM8903_DAC_DIGITAL_1, 12, 1, 0),
699SOC_ENUM("DAC Companding Mode", dac_companding), 701SOC_ENUM("DAC Companding Mode", dac_companding),
700SOC_SINGLE("DAC Companding Switch", WM8903_AUDIO_INTERFACE_0, 1, 1, 0), 702SOC_SINGLE("DAC Companding Switch", WM8903_AUDIO_INTERFACE_0, 1, 1, 0),
703SOC_SINGLE_TLV("DAC Boost Volume", WM8903_AUDIO_INTERFACE_0, 9, 3, 0,
704 dac_boost_tlv),
701SOC_SINGLE_BOOL_EXT("Playback Deemphasis Switch", 0, 705SOC_SINGLE_BOOL_EXT("Playback Deemphasis Switch", 0,
702 wm8903_get_deemph, wm8903_put_deemph), 706 wm8903_get_deemph, wm8903_put_deemph),
703 707
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index a64b93425ae3..0a4ffdd1d2a7 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -204,6 +204,7 @@ static const DECLARE_TLV_DB_SCALE(adc_tlv, -9700, 50, 0);
204static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 50, 1); 204static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 50, 1);
205static const DECLARE_TLV_DB_SCALE(bypass_tlv, -2100, 300, 0); 205static const DECLARE_TLV_DB_SCALE(bypass_tlv, -2100, 300, 0);
206static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); 206static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
207static const DECLARE_TLV_DB_SCALE(boost_tlv, -1200, 300, 1);
207 208
208static const struct snd_kcontrol_new wm8960_snd_controls[] = { 209static const struct snd_kcontrol_new wm8960_snd_controls[] = {
209SOC_DOUBLE_R_TLV("Capture Volume", WM8960_LINVOL, WM8960_RINVOL, 210SOC_DOUBLE_R_TLV("Capture Volume", WM8960_LINVOL, WM8960_RINVOL,
@@ -213,6 +214,15 @@ SOC_DOUBLE_R("Capture Volume ZC Switch", WM8960_LINVOL, WM8960_RINVOL,
213SOC_DOUBLE_R("Capture Switch", WM8960_LINVOL, WM8960_RINVOL, 214SOC_DOUBLE_R("Capture Switch", WM8960_LINVOL, WM8960_RINVOL,
214 7, 1, 0), 215 7, 1, 0),
215 216
217SOC_SINGLE_TLV("Right Input Boost Mixer RINPUT3 Volume",
218 WM8960_INBMIX1, 4, 7, 0, boost_tlv),
219SOC_SINGLE_TLV("Right Input Boost Mixer RINPUT2 Volume",
220 WM8960_INBMIX1, 1, 7, 0, boost_tlv),
221SOC_SINGLE_TLV("Left Input Boost Mixer LINPUT3 Volume",
222 WM8960_INBMIX2, 4, 7, 0, boost_tlv),
223SOC_SINGLE_TLV("Left Input Boost Mixer LINPUT2 Volume",
224 WM8960_INBMIX2, 1, 7, 0, boost_tlv),
225
216SOC_DOUBLE_R_TLV("Playback Volume", WM8960_LDAC, WM8960_RDAC, 226SOC_DOUBLE_R_TLV("Playback Volume", WM8960_LDAC, WM8960_RDAC,
217 0, 255, 0, dac_tlv), 227 0, 255, 0, dac_tlv),
218 228
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index c9bd445c4976..14094f558e03 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -2209,7 +2209,7 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
2209 vmid_reference(codec); 2209 vmid_reference(codec);
2210 break; 2210 break;
2211 case WM8958: 2211 case WM8958:
2212 if (wm8994->revision < 1) 2212 if (control->revision < 1)
2213 vmid_reference(codec); 2213 vmid_reference(codec);
2214 break; 2214 break;
2215 default: 2215 default:
@@ -2244,7 +2244,7 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
2244 vmid_dereference(codec); 2244 vmid_dereference(codec);
2245 break; 2245 break;
2246 case WM8958: 2246 case WM8958:
2247 if (wm8994->revision < 1) 2247 if (control->revision < 1)
2248 vmid_dereference(codec); 2248 vmid_dereference(codec);
2249 break; 2249 break;
2250 default: 2250 default:
@@ -2268,10 +2268,26 @@ out:
2268 */ 2268 */
2269 if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) { 2269 if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) {
2270 dev_dbg(codec->dev, "Configuring AIFs for 128fs\n"); 2270 dev_dbg(codec->dev, "Configuring AIFs for 128fs\n");
2271
2272 wm8994->aifdiv[0] = snd_soc_read(codec, WM8994_AIF1_RATE)
2273 & WM8994_AIF1CLK_RATE_MASK;
2274 wm8994->aifdiv[1] = snd_soc_read(codec, WM8994_AIF2_RATE)
2275 & WM8994_AIF1CLK_RATE_MASK;
2276
2271 snd_soc_update_bits(codec, WM8994_AIF1_RATE, 2277 snd_soc_update_bits(codec, WM8994_AIF1_RATE,
2272 WM8994_AIF1CLK_RATE_MASK, 0x1); 2278 WM8994_AIF1CLK_RATE_MASK, 0x1);
2273 snd_soc_update_bits(codec, WM8994_AIF2_RATE, 2279 snd_soc_update_bits(codec, WM8994_AIF2_RATE,
2274 WM8994_AIF2CLK_RATE_MASK, 0x1); 2280 WM8994_AIF2CLK_RATE_MASK, 0x1);
2281 } else if (wm8994->aifdiv[0]) {
2282 snd_soc_update_bits(codec, WM8994_AIF1_RATE,
2283 WM8994_AIF1CLK_RATE_MASK,
2284 wm8994->aifdiv[0]);
2285 snd_soc_update_bits(codec, WM8994_AIF2_RATE,
2286 WM8994_AIF2CLK_RATE_MASK,
2287 wm8994->aifdiv[1]);
2288
2289 wm8994->aifdiv[0] = 0;
2290 wm8994->aifdiv[1] = 0;
2275 } 2291 }
2276 2292
2277 return 0; 2293 return 0;
@@ -2368,10 +2384,26 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
2368 */ 2384 */
2369 if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) { 2385 if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) {
2370 dev_dbg(codec->dev, "Configuring AIFs for 128fs\n"); 2386 dev_dbg(codec->dev, "Configuring AIFs for 128fs\n");
2387
2388 wm8994->aifdiv[0] = snd_soc_read(codec, WM8994_AIF1_RATE)
2389 & WM8994_AIF1CLK_RATE_MASK;
2390 wm8994->aifdiv[1] = snd_soc_read(codec, WM8994_AIF2_RATE)
2391 & WM8994_AIF1CLK_RATE_MASK;
2392
2371 snd_soc_update_bits(codec, WM8994_AIF1_RATE, 2393 snd_soc_update_bits(codec, WM8994_AIF1_RATE,
2372 WM8994_AIF1CLK_RATE_MASK, 0x1); 2394 WM8994_AIF1CLK_RATE_MASK, 0x1);
2373 snd_soc_update_bits(codec, WM8994_AIF2_RATE, 2395 snd_soc_update_bits(codec, WM8994_AIF2_RATE,
2374 WM8994_AIF2CLK_RATE_MASK, 0x1); 2396 WM8994_AIF2CLK_RATE_MASK, 0x1);
2397 } else if (wm8994->aifdiv[0]) {
2398 snd_soc_update_bits(codec, WM8994_AIF1_RATE,
2399 WM8994_AIF1CLK_RATE_MASK,
2400 wm8994->aifdiv[0]);
2401 snd_soc_update_bits(codec, WM8994_AIF2_RATE,
2402 WM8994_AIF2CLK_RATE_MASK,
2403 wm8994->aifdiv[1]);
2404
2405 wm8994->aifdiv[0] = 0;
2406 wm8994->aifdiv[1] = 0;
2375 } 2407 }
2376 2408
2377 return 0; 2409 return 0;
@@ -2411,7 +2443,7 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
2411 if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { 2443 if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
2412 switch (control->type) { 2444 switch (control->type) {
2413 case WM8958: 2445 case WM8958:
2414 if (wm8994->revision == 0) { 2446 if (control->revision == 0) {
2415 /* Optimise performance for rev A */ 2447 /* Optimise performance for rev A */
2416 snd_soc_update_bits(codec, 2448 snd_soc_update_bits(codec,
2417 WM8958_CHARGE_PUMP_2, 2449 WM8958_CHARGE_PUMP_2,
@@ -2656,6 +2688,8 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
2656{ 2688{
2657 struct snd_soc_codec *codec = dai->codec; 2689 struct snd_soc_codec *codec = dai->codec;
2658 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); 2690 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
2691 struct wm8994 *control = wm8994->wm8994;
2692 struct wm8994_pdata *pdata = &control->pdata;
2659 int aif1_reg; 2693 int aif1_reg;
2660 int aif2_reg; 2694 int aif2_reg;
2661 int bclk_reg; 2695 int bclk_reg;
@@ -2723,7 +2757,14 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
2723 } 2757 }
2724 2758
2725 wm8994->channels[id] = params_channels(params); 2759 wm8994->channels[id] = params_channels(params);
2726 switch (params_channels(params)) { 2760 if (pdata->max_channels_clocked[id] &&
2761 wm8994->channels[id] > pdata->max_channels_clocked[id]) {
2762 dev_dbg(dai->dev, "Constraining channels to %d from %d\n",
2763 pdata->max_channels_clocked[id], wm8994->channels[id]);
2764 wm8994->channels[id] = pdata->max_channels_clocked[id];
2765 }
2766
2767 switch (wm8994->channels[id]) {
2727 case 1: 2768 case 1:
2728 case 2: 2769 case 2:
2729 bclk_rate *= 2; 2770 bclk_rate *= 2;
@@ -2745,7 +2786,7 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
2745 dev_dbg(dai->dev, "AIF%dCLK is %dHz, target BCLK %dHz\n", 2786 dev_dbg(dai->dev, "AIF%dCLK is %dHz, target BCLK %dHz\n",
2746 dai->id, wm8994->aifclk[id], bclk_rate); 2787 dai->id, wm8994->aifclk[id], bclk_rate);
2747 2788
2748 if (params_channels(params) == 1 && 2789 if (wm8994->channels[id] == 1 &&
2749 (snd_soc_read(codec, aif1_reg) & 0x18) == 0x18) 2790 (snd_soc_read(codec, aif1_reg) & 0x18) == 0x18)
2750 aif2 |= WM8994_AIF1_MONO; 2791 aif2 |= WM8994_AIF1_MONO;
2751 2792
@@ -3053,7 +3094,7 @@ static int wm8994_codec_resume(struct snd_soc_codec *codec)
3053 int i, ret; 3094 int i, ret;
3054 unsigned int val, mask; 3095 unsigned int val, mask;
3055 3096
3056 if (wm8994->revision < 4) { 3097 if (control->revision < 4) {
3057 /* force a HW read */ 3098 /* force a HW read */
3058 ret = regmap_read(control->regmap, 3099 ret = regmap_read(control->regmap,
3059 WM8994_POWER_MANAGEMENT_5, &val); 3100 WM8994_POWER_MANAGEMENT_5, &val);
@@ -3870,7 +3911,6 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
3870 codec->dapm.idle_bias_off = 1; 3911 codec->dapm.idle_bias_off = 1;
3871 3912
3872 /* Set revision-specific configuration */ 3913 /* Set revision-specific configuration */
3873 wm8994->revision = snd_soc_read(codec, WM8994_CHIP_REVISION);
3874 switch (control->type) { 3914 switch (control->type) {
3875 case WM8994: 3915 case WM8994:
3876 /* Single ended line outputs should have VMID on. */ 3916 /* Single ended line outputs should have VMID on. */
@@ -3878,7 +3918,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
3878 !control->pdata.lineout2_diff) 3918 !control->pdata.lineout2_diff)
3879 codec->dapm.idle_bias_off = 0; 3919 codec->dapm.idle_bias_off = 0;
3880 3920
3881 switch (wm8994->revision) { 3921 switch (control->revision) {
3882 case 2: 3922 case 2:
3883 case 3: 3923 case 3:
3884 wm8994->hubs.dcs_codes_l = -5; 3924 wm8994->hubs.dcs_codes_l = -5;
@@ -3897,7 +3937,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
3897 wm8994->hubs.dcs_readback_mode = 1; 3937 wm8994->hubs.dcs_readback_mode = 1;
3898 wm8994->hubs.hp_startup_mode = 1; 3938 wm8994->hubs.hp_startup_mode = 1;
3899 3939
3900 switch (wm8994->revision) { 3940 switch (control->revision) {
3901 case 0: 3941 case 0:
3902 break; 3942 break;
3903 default: 3943 default:
@@ -4000,7 +4040,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
4000 4040
4001 switch (control->type) { 4041 switch (control->type) {
4002 case WM1811: 4042 case WM1811:
4003 if (control->cust_id > 1 || wm8994->revision > 1) { 4043 if (control->cust_id > 1 || control->revision > 1) {
4004 ret = wm8994_request_irq(wm8994->wm8994, 4044 ret = wm8994_request_irq(wm8994->wm8994,
4005 WM8994_IRQ_GPIO(6), 4045 WM8994_IRQ_GPIO(6),
4006 wm1811_jackdet_irq, "JACKDET", 4046 wm1811_jackdet_irq, "JACKDET",
@@ -4114,7 +4154,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
4114 case WM8994: 4154 case WM8994:
4115 snd_soc_dapm_new_controls(dapm, wm8994_specific_dapm_widgets, 4155 snd_soc_dapm_new_controls(dapm, wm8994_specific_dapm_widgets,
4116 ARRAY_SIZE(wm8994_specific_dapm_widgets)); 4156 ARRAY_SIZE(wm8994_specific_dapm_widgets));
4117 if (wm8994->revision < 4) { 4157 if (control->revision < 4) {
4118 snd_soc_dapm_new_controls(dapm, wm8994_lateclk_revd_widgets, 4158 snd_soc_dapm_new_controls(dapm, wm8994_lateclk_revd_widgets,
4119 ARRAY_SIZE(wm8994_lateclk_revd_widgets)); 4159 ARRAY_SIZE(wm8994_lateclk_revd_widgets));
4120 snd_soc_dapm_new_controls(dapm, wm8994_adc_revd_widgets, 4160 snd_soc_dapm_new_controls(dapm, wm8994_adc_revd_widgets,
@@ -4135,7 +4175,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
4135 ARRAY_SIZE(wm8958_snd_controls)); 4175 ARRAY_SIZE(wm8958_snd_controls));
4136 snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets, 4176 snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets,
4137 ARRAY_SIZE(wm8958_dapm_widgets)); 4177 ARRAY_SIZE(wm8958_dapm_widgets));
4138 if (wm8994->revision < 1) { 4178 if (control->revision < 1) {
4139 snd_soc_dapm_new_controls(dapm, wm8994_lateclk_revd_widgets, 4179 snd_soc_dapm_new_controls(dapm, wm8994_lateclk_revd_widgets,
4140 ARRAY_SIZE(wm8994_lateclk_revd_widgets)); 4180 ARRAY_SIZE(wm8994_lateclk_revd_widgets));
4141 snd_soc_dapm_new_controls(dapm, wm8994_adc_revd_widgets, 4181 snd_soc_dapm_new_controls(dapm, wm8994_adc_revd_widgets,
@@ -4174,7 +4214,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
4174 snd_soc_dapm_add_routes(dapm, wm8994_intercon, 4214 snd_soc_dapm_add_routes(dapm, wm8994_intercon,
4175 ARRAY_SIZE(wm8994_intercon)); 4215 ARRAY_SIZE(wm8994_intercon));
4176 4216
4177 if (wm8994->revision < 4) { 4217 if (control->revision < 4) {
4178 snd_soc_dapm_add_routes(dapm, wm8994_revd_intercon, 4218 snd_soc_dapm_add_routes(dapm, wm8994_revd_intercon,
4179 ARRAY_SIZE(wm8994_revd_intercon)); 4219 ARRAY_SIZE(wm8994_revd_intercon));
4180 snd_soc_dapm_add_routes(dapm, wm8994_lateclk_revd_intercon, 4220 snd_soc_dapm_add_routes(dapm, wm8994_lateclk_revd_intercon,
@@ -4185,7 +4225,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
4185 } 4225 }
4186 break; 4226 break;
4187 case WM8958: 4227 case WM8958:
4188 if (wm8994->revision < 1) { 4228 if (control->revision < 1) {
4189 snd_soc_dapm_add_routes(dapm, wm8994_intercon, 4229 snd_soc_dapm_add_routes(dapm, wm8994_intercon,
4190 ARRAY_SIZE(wm8994_intercon)); 4230 ARRAY_SIZE(wm8994_intercon));
4191 snd_soc_dapm_add_routes(dapm, wm8994_revd_intercon, 4231 snd_soc_dapm_add_routes(dapm, wm8994_revd_intercon,
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h
index 45f192702024..55ddf4d57d9b 100644
--- a/sound/soc/codecs/wm8994.h
+++ b/sound/soc/codecs/wm8994.h
@@ -79,6 +79,7 @@ struct wm8994_priv {
79 int sysclk_rate[2]; 79 int sysclk_rate[2];
80 int mclk[2]; 80 int mclk[2];
81 int aifclk[2]; 81 int aifclk[2];
82 int aifdiv[2];
82 int channels[2]; 83 int channels[2];
83 struct wm8994_fll_config fll[2], fll_suspend[2]; 84 struct wm8994_fll_config fll[2], fll_suspend[2];
84 struct completion fll_locked[2]; 85 struct completion fll_locked[2];
@@ -146,8 +147,6 @@ struct wm8994_priv {
146 wm1811_mic_id_cb mic_id_cb; 147 wm1811_mic_id_cb mic_id_cb;
147 void *mic_id_cb_data; 148 void *mic_id_cb_data;
148 149
149 int revision;
150
151 unsigned int aif1clk_enable:1; 150 unsigned int aif1clk_enable:1;
152 unsigned int aif2clk_enable:1; 151 unsigned int aif2clk_enable:1;
153 152
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index 9af1bddc4c62..3470b649c0b2 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -31,6 +31,7 @@
31 31
32#include <linux/mfd/arizona/registers.h> 32#include <linux/mfd/arizona/registers.h>
33 33
34#include "arizona.h"
34#include "wm_adsp.h" 35#include "wm_adsp.h"
35 36
36#define adsp_crit(_dsp, fmt, ...) \ 37#define adsp_crit(_dsp, fmt, ...) \
@@ -193,17 +194,25 @@ static void wm_adsp_buf_free(struct list_head *list)
193 194
194#define WM_ADSP_NUM_FW 4 195#define WM_ADSP_NUM_FW 4
195 196
197#define WM_ADSP_FW_MBC_VSS 0
198#define WM_ADSP_FW_TX 1
199#define WM_ADSP_FW_TX_SPK 2
200#define WM_ADSP_FW_RX_ANC 3
201
196static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = { 202static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = {
197 "MBC/VSS", "Tx", "Tx Speaker", "Rx ANC" 203 [WM_ADSP_FW_MBC_VSS] = "MBC/VSS",
204 [WM_ADSP_FW_TX] = "Tx",
205 [WM_ADSP_FW_TX_SPK] = "Tx Speaker",
206 [WM_ADSP_FW_RX_ANC] = "Rx ANC",
198}; 207};
199 208
200static struct { 209static struct {
201 const char *file; 210 const char *file;
202} wm_adsp_fw[WM_ADSP_NUM_FW] = { 211} wm_adsp_fw[WM_ADSP_NUM_FW] = {
203 { .file = "mbc-vss" }, 212 [WM_ADSP_FW_MBC_VSS] = { .file = "mbc-vss" },
204 { .file = "tx" }, 213 [WM_ADSP_FW_TX] = { .file = "tx" },
205 { .file = "tx-spk" }, 214 [WM_ADSP_FW_TX_SPK] = { .file = "tx-spk" },
206 { .file = "rx-anc" }, 215 [WM_ADSP_FW_RX_ANC] = { .file = "rx-anc" },
207}; 216};
208 217
209static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, 218static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
@@ -246,17 +255,52 @@ static const struct soc_enum wm_adsp_fw_enum[] = {
246 SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), 255 SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
247}; 256};
248 257
249const struct snd_kcontrol_new wm_adsp_fw_controls[] = { 258const struct snd_kcontrol_new wm_adsp1_fw_controls[] = {
259 SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0],
260 wm_adsp_fw_get, wm_adsp_fw_put),
261 SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1],
262 wm_adsp_fw_get, wm_adsp_fw_put),
263 SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2],
264 wm_adsp_fw_get, wm_adsp_fw_put),
265};
266EXPORT_SYMBOL_GPL(wm_adsp1_fw_controls);
267
268#if IS_ENABLED(CONFIG_SND_SOC_ARIZONA)
269static const struct soc_enum wm_adsp2_rate_enum[] = {
270 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP1_CONTROL_1,
271 ARIZONA_DSP1_RATE_SHIFT, 0xf,
272 ARIZONA_RATE_ENUM_SIZE,
273 arizona_rate_text, arizona_rate_val),
274 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP2_CONTROL_1,
275 ARIZONA_DSP1_RATE_SHIFT, 0xf,
276 ARIZONA_RATE_ENUM_SIZE,
277 arizona_rate_text, arizona_rate_val),
278 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP3_CONTROL_1,
279 ARIZONA_DSP1_RATE_SHIFT, 0xf,
280 ARIZONA_RATE_ENUM_SIZE,
281 arizona_rate_text, arizona_rate_val),
282 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP3_CONTROL_1,
283 ARIZONA_DSP1_RATE_SHIFT, 0xf,
284 ARIZONA_RATE_ENUM_SIZE,
285 arizona_rate_text, arizona_rate_val),
286};
287
288const struct snd_kcontrol_new wm_adsp2_fw_controls[] = {
250 SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0], 289 SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0],
251 wm_adsp_fw_get, wm_adsp_fw_put), 290 wm_adsp_fw_get, wm_adsp_fw_put),
291 SOC_ENUM("DSP1 Rate", wm_adsp2_rate_enum[0]),
252 SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1], 292 SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1],
253 wm_adsp_fw_get, wm_adsp_fw_put), 293 wm_adsp_fw_get, wm_adsp_fw_put),
294 SOC_ENUM("DSP2 Rate", wm_adsp2_rate_enum[1]),
254 SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2], 295 SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2],
255 wm_adsp_fw_get, wm_adsp_fw_put), 296 wm_adsp_fw_get, wm_adsp_fw_put),
297 SOC_ENUM("DSP3 Rate", wm_adsp2_rate_enum[2]),
256 SOC_ENUM_EXT("DSP4 Firmware", wm_adsp_fw_enum[3], 298 SOC_ENUM_EXT("DSP4 Firmware", wm_adsp_fw_enum[3],
257 wm_adsp_fw_get, wm_adsp_fw_put), 299 wm_adsp_fw_get, wm_adsp_fw_put),
300 SOC_ENUM("DSP4 Rate", wm_adsp2_rate_enum[3]),
258}; 301};
259EXPORT_SYMBOL_GPL(wm_adsp_fw_controls); 302EXPORT_SYMBOL_GPL(wm_adsp2_fw_controls);
303#endif
260 304
261static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp, 305static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp,
262 int type) 306 int type)
@@ -549,13 +593,30 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
549 buf_size = sizeof(adsp1_id); 593 buf_size = sizeof(adsp1_id);
550 594
551 algs = be32_to_cpu(adsp1_id.algs); 595 algs = be32_to_cpu(adsp1_id.algs);
596 dsp->fw_id = be32_to_cpu(adsp1_id.fw.id);
552 adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n", 597 adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
553 be32_to_cpu(adsp1_id.fw.id), 598 dsp->fw_id,
554 (be32_to_cpu(adsp1_id.fw.ver) & 0xff0000) >> 16, 599 (be32_to_cpu(adsp1_id.fw.ver) & 0xff0000) >> 16,
555 (be32_to_cpu(adsp1_id.fw.ver) & 0xff00) >> 8, 600 (be32_to_cpu(adsp1_id.fw.ver) & 0xff00) >> 8,
556 be32_to_cpu(adsp1_id.fw.ver) & 0xff, 601 be32_to_cpu(adsp1_id.fw.ver) & 0xff,
557 algs); 602 algs);
558 603
604 region = kzalloc(sizeof(*region), GFP_KERNEL);
605 if (!region)
606 return -ENOMEM;
607 region->type = WMFW_ADSP1_ZM;
608 region->alg = be32_to_cpu(adsp1_id.fw.id);
609 region->base = be32_to_cpu(adsp1_id.zm);
610 list_add_tail(&region->list, &dsp->alg_regions);
611
612 region = kzalloc(sizeof(*region), GFP_KERNEL);
613 if (!region)
614 return -ENOMEM;
615 region->type = WMFW_ADSP1_DM;
616 region->alg = be32_to_cpu(adsp1_id.fw.id);
617 region->base = be32_to_cpu(adsp1_id.dm);
618 list_add_tail(&region->list, &dsp->alg_regions);
619
559 pos = sizeof(adsp1_id) / 2; 620 pos = sizeof(adsp1_id) / 2;
560 term = pos + ((sizeof(*adsp1_alg) * algs) / 2); 621 term = pos + ((sizeof(*adsp1_alg) * algs) / 2);
561 break; 622 break;
@@ -573,13 +634,38 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
573 buf_size = sizeof(adsp2_id); 634 buf_size = sizeof(adsp2_id);
574 635
575 algs = be32_to_cpu(adsp2_id.algs); 636 algs = be32_to_cpu(adsp2_id.algs);
637 dsp->fw_id = be32_to_cpu(adsp2_id.fw.id);
576 adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n", 638 adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
577 be32_to_cpu(adsp2_id.fw.id), 639 dsp->fw_id,
578 (be32_to_cpu(adsp2_id.fw.ver) & 0xff0000) >> 16, 640 (be32_to_cpu(adsp2_id.fw.ver) & 0xff0000) >> 16,
579 (be32_to_cpu(adsp2_id.fw.ver) & 0xff00) >> 8, 641 (be32_to_cpu(adsp2_id.fw.ver) & 0xff00) >> 8,
580 be32_to_cpu(adsp2_id.fw.ver) & 0xff, 642 be32_to_cpu(adsp2_id.fw.ver) & 0xff,
581 algs); 643 algs);
582 644
645 region = kzalloc(sizeof(*region), GFP_KERNEL);
646 if (!region)
647 return -ENOMEM;
648 region->type = WMFW_ADSP2_XM;
649 region->alg = be32_to_cpu(adsp2_id.fw.id);
650 region->base = be32_to_cpu(adsp2_id.xm);
651 list_add_tail(&region->list, &dsp->alg_regions);
652
653 region = kzalloc(sizeof(*region), GFP_KERNEL);
654 if (!region)
655 return -ENOMEM;
656 region->type = WMFW_ADSP2_YM;
657 region->alg = be32_to_cpu(adsp2_id.fw.id);
658 region->base = be32_to_cpu(adsp2_id.ym);
659 list_add_tail(&region->list, &dsp->alg_regions);
660
661 region = kzalloc(sizeof(*region), GFP_KERNEL);
662 if (!region)
663 return -ENOMEM;
664 region->type = WMFW_ADSP2_ZM;
665 region->alg = be32_to_cpu(adsp2_id.fw.id);
666 region->base = be32_to_cpu(adsp2_id.zm);
667 list_add_tail(&region->list, &dsp->alg_regions);
668
583 pos = sizeof(adsp2_id) / 2; 669 pos = sizeof(adsp2_id) / 2;
584 term = pos + ((sizeof(*adsp2_alg) * algs) / 2); 670 term = pos + ((sizeof(*adsp2_alg) * algs) / 2);
585 break; 671 break;
@@ -781,8 +867,24 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
781 case (WMFW_INFO_TEXT << 8): 867 case (WMFW_INFO_TEXT << 8):
782 break; 868 break;
783 case (WMFW_ABSOLUTE << 8): 869 case (WMFW_ABSOLUTE << 8):
784 region_name = "register"; 870 /*
785 reg = offset; 871 * Old files may use this for global
872 * coefficients.
873 */
874 if (le32_to_cpu(blk->id) == dsp->fw_id &&
875 offset == 0) {
876 region_name = "global coefficients";
877 mem = wm_adsp_find_region(dsp, type);
878 if (!mem) {
879 adsp_err(dsp, "No ZM\n");
880 break;
881 }
882 reg = wm_adsp_region_to_reg(mem, 0);
883
884 } else {
885 region_name = "register";
886 reg = offset;
887 }
786 break; 888 break;
787 889
788 case WMFW_ADSP1_DM: 890 case WMFW_ADSP1_DM:
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h
index cb8871a3ec00..fea514627526 100644
--- a/sound/soc/codecs/wm_adsp.h
+++ b/sound/soc/codecs/wm_adsp.h
@@ -46,6 +46,8 @@ struct wm_adsp {
46 46
47 struct list_head alg_regions; 47 struct list_head alg_regions;
48 48
49 int fw_id;
50
49 const struct wm_adsp_region *mem; 51 const struct wm_adsp_region *mem;
50 int num_mems; 52 int num_mems;
51 53
@@ -65,7 +67,8 @@ struct wm_adsp {
65 .shift = num, .event = wm_adsp2_event, \ 67 .shift = num, .event = wm_adsp2_event, \
66 .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD } 68 .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD }
67 69
68extern const struct snd_kcontrol_new wm_adsp_fw_controls[]; 70extern const struct snd_kcontrol_new wm_adsp1_fw_controls[];
71extern const struct snd_kcontrol_new wm_adsp2_fw_controls[];
69 72
70int wm_adsp1_init(struct wm_adsp *adsp); 73int wm_adsp1_init(struct wm_adsp *adsp);
71int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs); 74int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs);
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index 867ae97ddcec..f5d81b948759 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -199,11 +199,12 @@ static void wm_hubs_dcs_cache_set(struct snd_soc_codec *codec, u16 dcs_cfg)
199 list_add_tail(&cache->list, &hubs->dcs_cache); 199 list_add_tail(&cache->list, &hubs->dcs_cache);
200} 200}
201 201
202static void wm_hubs_read_dc_servo(struct snd_soc_codec *codec, 202static int wm_hubs_read_dc_servo(struct snd_soc_codec *codec,
203 u16 *reg_l, u16 *reg_r) 203 u16 *reg_l, u16 *reg_r)
204{ 204{
205 struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); 205 struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
206 u16 dcs_reg, reg; 206 u16 dcs_reg, reg;
207 int ret = 0;
207 208
208 switch (hubs->dcs_readback_mode) { 209 switch (hubs->dcs_readback_mode) {
209 case 2: 210 case 2:
@@ -236,8 +237,9 @@ static void wm_hubs_read_dc_servo(struct snd_soc_codec *codec,
236 break; 237 break;
237 default: 238 default:
238 WARN(1, "Unknown DCS readback method\n"); 239 WARN(1, "Unknown DCS readback method\n");
239 return; 240 ret = -1;
240 } 241 }
242 return ret;
241} 243}
242 244
243/* 245/*
@@ -286,7 +288,8 @@ static void enable_dc_servo(struct snd_soc_codec *codec)
286 WM8993_DCS_TRIG_STARTUP_1); 288 WM8993_DCS_TRIG_STARTUP_1);
287 } 289 }
288 290
289 wm_hubs_read_dc_servo(codec, &reg_l, &reg_r); 291 if (wm_hubs_read_dc_servo(codec, &reg_l, &reg_r) < 0)
292 return;
290 293
291 dev_dbg(codec->dev, "DCS input: %x %x\n", reg_l, reg_r); 294 dev_dbg(codec->dev, "DCS input: %x %x\n", reg_l, reg_r);
292 295
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index 821831207180..ebe82947bab3 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -645,6 +645,10 @@ static struct snd_soc_dai_driver davinci_i2s_dai = {
645 645
646}; 646};
647 647
648static const struct snd_soc_component_driver davinci_i2s_component = {
649 .name = "davinci-i2s",
650};
651
648static int davinci_i2s_probe(struct platform_device *pdev) 652static int davinci_i2s_probe(struct platform_device *pdev)
649{ 653{
650 struct snd_platform_data *pdata = pdev->dev.platform_data; 654 struct snd_platform_data *pdata = pdev->dev.platform_data;
@@ -727,20 +731,21 @@ static int davinci_i2s_probe(struct platform_device *pdev)
727 731
728 dev_set_drvdata(&pdev->dev, dev); 732 dev_set_drvdata(&pdev->dev, dev);
729 733
730 ret = snd_soc_register_dai(&pdev->dev, &davinci_i2s_dai); 734 ret = snd_soc_register_component(&pdev->dev, &davinci_i2s_component,
735 &davinci_i2s_dai, 1);
731 if (ret != 0) 736 if (ret != 0)
732 goto err_release_clk; 737 goto err_release_clk;
733 738
734 ret = davinci_soc_platform_register(&pdev->dev); 739 ret = davinci_soc_platform_register(&pdev->dev);
735 if (ret) { 740 if (ret) {
736 dev_err(&pdev->dev, "register PCM failed: %d\n", ret); 741 dev_err(&pdev->dev, "register PCM failed: %d\n", ret);
737 goto err_unregister_dai; 742 goto err_unregister_component;
738 } 743 }
739 744
740 return 0; 745 return 0;
741 746
742err_unregister_dai: 747err_unregister_component:
743 snd_soc_unregister_dai(&pdev->dev); 748 snd_soc_unregister_component(&pdev->dev);
744err_release_clk: 749err_release_clk:
745 clk_disable(dev->clk); 750 clk_disable(dev->clk);
746 clk_put(dev->clk); 751 clk_put(dev->clk);
@@ -751,7 +756,7 @@ static int davinci_i2s_remove(struct platform_device *pdev)
751{ 756{
752 struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev); 757 struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev);
753 758
754 snd_soc_unregister_dai(&pdev->dev); 759 snd_soc_unregister_component(&pdev->dev);
755 davinci_soc_platform_unregister(&pdev->dev); 760 davinci_soc_platform_unregister(&pdev->dev);
756 761
757 clk_disable(dev->clk); 762 clk_disable(dev->clk);
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 9321e5c9d8c1..8b85049daab0 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -235,6 +235,8 @@
235#define DISMOD (val)(val<<2) 235#define DISMOD (val)(val<<2)
236#define TXSTATE BIT(4) 236#define TXSTATE BIT(4)
237#define RXSTATE BIT(5) 237#define RXSTATE BIT(5)
238#define SRMOD_MASK 3
239#define SRMOD_INACTIVE 0
238 240
239/* 241/*
240 * DAVINCI_MCASP_LBCTL_REG - Loop Back Control Register Bits 242 * DAVINCI_MCASP_LBCTL_REG - Loop Back Control Register Bits
@@ -634,35 +636,43 @@ static int davinci_config_channel_size(struct davinci_audio_dev *dev,
634 * callback, take it into account here. That allows us to for example 636 * callback, take it into account here. That allows us to for example
635 * send 32 bits per channel to the codec, while only 16 of them carry 637 * send 32 bits per channel to the codec, while only 16 of them carry
636 * audio payload. 638 * audio payload.
637 * The clock ratio is given for a full period of data (both left and 639 * The clock ratio is given for a full period of data (for I2S format
638 * right channels), so it has to be divided by 2. 640 * both left and right channels), so it has to be divided by number of
641 * tdm-slots (for I2S - divided by 2).
639 */ 642 */
640 if (dev->bclk_lrclk_ratio) 643 if (dev->bclk_lrclk_ratio)
641 word_length = dev->bclk_lrclk_ratio / 2; 644 word_length = dev->bclk_lrclk_ratio / dev->tdm_slots;
642 645
643 /* mapping of the XSSZ bit-field as described in the datasheet */ 646 /* mapping of the XSSZ bit-field as described in the datasheet */
644 fmt = (word_length >> 1) - 1; 647 fmt = (word_length >> 1) - 1;
645 648
646 mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, 649 if (dev->op_mode != DAVINCI_MCASP_DIT_MODE) {
647 RXSSZ(fmt), RXSSZ(0x0F)); 650 mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG,
648 mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, 651 RXSSZ(fmt), RXSSZ(0x0F));
649 TXSSZ(fmt), TXSSZ(0x0F)); 652 mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
650 mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXROT(rotate), 653 TXSSZ(fmt), TXSSZ(0x0F));
651 TXROT(7)); 654 mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
652 mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXROT(rotate), 655 TXROT(rotate), TXROT(7));
653 RXROT(7)); 656 mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG,
657 RXROT(rotate), RXROT(7));
658 mcasp_set_reg(dev->base + DAVINCI_MCASP_RXMASK_REG,
659 mask);
660 }
661
654 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, mask); 662 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, mask);
655 mcasp_set_reg(dev->base + DAVINCI_MCASP_RXMASK_REG, mask);
656 663
657 return 0; 664 return 0;
658} 665}
659 666
660static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream) 667static int davinci_hw_common_param(struct davinci_audio_dev *dev, int stream,
668 int channels)
661{ 669{
662 int i; 670 int i;
663 u8 tx_ser = 0; 671 u8 tx_ser = 0;
664 u8 rx_ser = 0; 672 u8 rx_ser = 0;
665 673 u8 ser;
674 u8 slots = dev->tdm_slots;
675 u8 max_active_serializers = (channels + slots - 1) / slots;
666 /* Default configuration */ 676 /* Default configuration */
667 mcasp_set_bits(dev->base + DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT); 677 mcasp_set_bits(dev->base + DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT);
668 678
@@ -682,17 +692,33 @@ static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream)
682 for (i = 0; i < dev->num_serializer; i++) { 692 for (i = 0; i < dev->num_serializer; i++) {
683 mcasp_set_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i), 693 mcasp_set_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i),
684 dev->serial_dir[i]); 694 dev->serial_dir[i]);
685 if (dev->serial_dir[i] == TX_MODE) { 695 if (dev->serial_dir[i] == TX_MODE &&
696 tx_ser < max_active_serializers) {
686 mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, 697 mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG,
687 AXR(i)); 698 AXR(i));
688 tx_ser++; 699 tx_ser++;
689 } else if (dev->serial_dir[i] == RX_MODE) { 700 } else if (dev->serial_dir[i] == RX_MODE &&
701 rx_ser < max_active_serializers) {
690 mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG, 702 mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG,
691 AXR(i)); 703 AXR(i));
692 rx_ser++; 704 rx_ser++;
705 } else {
706 mcasp_mod_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i),
707 SRMOD_INACTIVE, SRMOD_MASK);
693 } 708 }
694 } 709 }
695 710
711 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
712 ser = tx_ser;
713 else
714 ser = rx_ser;
715
716 if (ser < max_active_serializers) {
717 dev_warn(dev->dev, "stream has more channels (%d) than are "
718 "enabled in mcasp (%d)\n", channels, ser * slots);
719 return -EINVAL;
720 }
721
696 if (dev->txnumevt && stream == SNDRV_PCM_STREAM_PLAYBACK) { 722 if (dev->txnumevt && stream == SNDRV_PCM_STREAM_PLAYBACK) {
697 if (dev->txnumevt * tx_ser > 64) 723 if (dev->txnumevt * tx_ser > 64)
698 dev->txnumevt = 1; 724 dev->txnumevt = 1;
@@ -729,6 +755,8 @@ static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream)
729 ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK); 755 ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK);
730 } 756 }
731 } 757 }
758
759 return 0;
732} 760}
733 761
734static void davinci_hw_param(struct davinci_audio_dev *dev, int stream) 762static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
@@ -772,12 +800,6 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
772/* S/PDIF */ 800/* S/PDIF */
773static void davinci_hw_dit_param(struct davinci_audio_dev *dev) 801static void davinci_hw_dit_param(struct davinci_audio_dev *dev)
774{ 802{
775 /* Set the PDIR for Serialiser as output */
776 mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AFSX);
777
778 /* TXMASK for 24 bits */
779 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, 0x00FFFFFF);
780
781 /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0 803 /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0
782 and LSB first */ 804 and LSB first */
783 mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, 805 mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
@@ -812,12 +834,21 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
812 &dev->dma_params[substream->stream]; 834 &dev->dma_params[substream->stream];
813 int word_length; 835 int word_length;
814 u8 fifo_level; 836 u8 fifo_level;
837 u8 slots = dev->tdm_slots;
838 u8 active_serializers;
839 int channels;
840 struct snd_interval *pcm_channels = hw_param_interval(params,
841 SNDRV_PCM_HW_PARAM_CHANNELS);
842 channels = pcm_channels->min;
843
844 active_serializers = (channels + slots - 1) / slots;
815 845
816 davinci_hw_common_param(dev, substream->stream); 846 if (davinci_hw_common_param(dev, substream->stream, channels) == -EINVAL)
847 return -EINVAL;
817 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 848 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
818 fifo_level = dev->txnumevt; 849 fifo_level = dev->txnumevt * active_serializers;
819 else 850 else
820 fifo_level = dev->rxnumevt; 851 fifo_level = dev->rxnumevt * active_serializers;
821 852
822 if (dev->op_mode == DAVINCI_MCASP_DIT_MODE) 853 if (dev->op_mode == DAVINCI_MCASP_DIT_MODE)
823 davinci_hw_dit_param(dev); 854 davinci_hw_dit_param(dev);
@@ -936,13 +967,13 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
936 .name = "davinci-mcasp.0", 967 .name = "davinci-mcasp.0",
937 .playback = { 968 .playback = {
938 .channels_min = 2, 969 .channels_min = 2,
939 .channels_max = 2, 970 .channels_max = 32 * 16,
940 .rates = DAVINCI_MCASP_RATES, 971 .rates = DAVINCI_MCASP_RATES,
941 .formats = DAVINCI_MCASP_PCM_FMTS, 972 .formats = DAVINCI_MCASP_PCM_FMTS,
942 }, 973 },
943 .capture = { 974 .capture = {
944 .channels_min = 2, 975 .channels_min = 2,
945 .channels_max = 2, 976 .channels_max = 32 * 16,
946 .rates = DAVINCI_MCASP_RATES, 977 .rates = DAVINCI_MCASP_RATES,
947 .formats = DAVINCI_MCASP_PCM_FMTS, 978 .formats = DAVINCI_MCASP_PCM_FMTS,
948 }, 979 },
@@ -962,6 +993,10 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
962 993
963}; 994};
964 995
996static const struct snd_soc_component_driver davinci_mcasp_component = {
997 .name = "davinci-mcasp",
998};
999
965static const struct of_device_id mcasp_dt_ids[] = { 1000static const struct of_device_id mcasp_dt_ids[] = {
966 { 1001 {
967 .compatible = "ti,dm646x-mcasp-audio", 1002 .compatible = "ti,dm646x-mcasp-audio",
@@ -1015,8 +1050,16 @@ static struct snd_platform_data *davinci_mcasp_set_pdata_from_of(
1015 pdata->op_mode = val; 1050 pdata->op_mode = val;
1016 1051
1017 ret = of_property_read_u32(np, "tdm-slots", &val); 1052 ret = of_property_read_u32(np, "tdm-slots", &val);
1018 if (ret >= 0) 1053 if (ret >= 0) {
1054 if (val < 2 || val > 32) {
1055 dev_err(&pdev->dev,
1056 "tdm-slots must be in rage [2-32]\n");
1057 ret = -EINVAL;
1058 goto nodata;
1059 }
1060
1019 pdata->tdm_slots = val; 1061 pdata->tdm_slots = val;
1062 }
1020 1063
1021 ret = of_property_read_u32(np, "num-serializer", &val); 1064 ret = of_property_read_u32(np, "num-serializer", &val);
1022 if (ret >= 0) 1065 if (ret >= 0)
@@ -1170,7 +1213,8 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
1170 1213
1171 dma_data->channel = res->start; 1214 dma_data->channel = res->start;
1172 dev_set_drvdata(&pdev->dev, dev); 1215 dev_set_drvdata(&pdev->dev, dev);
1173 ret = snd_soc_register_dai(&pdev->dev, &davinci_mcasp_dai[pdata->op_mode]); 1216 ret = snd_soc_register_component(&pdev->dev, &davinci_mcasp_component,
1217 &davinci_mcasp_dai[pdata->op_mode], 1);
1174 1218
1175 if (ret != 0) 1219 if (ret != 0)
1176 goto err_release_clk; 1220 goto err_release_clk;
@@ -1178,13 +1222,13 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
1178 ret = davinci_soc_platform_register(&pdev->dev); 1222 ret = davinci_soc_platform_register(&pdev->dev);
1179 if (ret) { 1223 if (ret) {
1180 dev_err(&pdev->dev, "register PCM failed: %d\n", ret); 1224 dev_err(&pdev->dev, "register PCM failed: %d\n", ret);
1181 goto err_unregister_dai; 1225 goto err_unregister_component;
1182 } 1226 }
1183 1227
1184 return 0; 1228 return 0;
1185 1229
1186err_unregister_dai: 1230err_unregister_component:
1187 snd_soc_unregister_dai(&pdev->dev); 1231 snd_soc_unregister_component(&pdev->dev);
1188err_release_clk: 1232err_release_clk:
1189 pm_runtime_put_sync(&pdev->dev); 1233 pm_runtime_put_sync(&pdev->dev);
1190 pm_runtime_disable(&pdev->dev); 1234 pm_runtime_disable(&pdev->dev);
@@ -1194,7 +1238,7 @@ err_release_clk:
1194static int davinci_mcasp_remove(struct platform_device *pdev) 1238static int davinci_mcasp_remove(struct platform_device *pdev)
1195{ 1239{
1196 1240
1197 snd_soc_unregister_dai(&pdev->dev); 1241 snd_soc_unregister_component(&pdev->dev);
1198 davinci_soc_platform_unregister(&pdev->dev); 1242 davinci_soc_platform_unregister(&pdev->dev);
1199 1243
1200 pm_runtime_put_sync(&pdev->dev); 1244 pm_runtime_put_sync(&pdev->dev);
diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h
index 0edd3b5a37fd..a9ac0c11da71 100644
--- a/sound/soc/davinci/davinci-mcasp.h
+++ b/sound/soc/davinci/davinci-mcasp.h
@@ -38,7 +38,7 @@ struct davinci_audio_dev {
38 u8 num_serializer; 38 u8 num_serializer;
39 u8 *serial_dir; 39 u8 *serial_dir;
40 u8 version; 40 u8 version;
41 u8 bclk_lrclk_ratio; 41 u16 bclk_lrclk_ratio;
42 42
43 /* McASP FIFO related */ 43 /* McASP FIFO related */
44 u8 txnumevt; 44 u8 txnumevt;
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index afab81f844ae..b2f27c2e5fdc 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -200,7 +200,7 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
200 src = dma_pos; 200 src = dma_pos;
201 dst = prtd->params->dma_addr; 201 dst = prtd->params->dma_addr;
202 src_bidx = data_type; 202 src_bidx = data_type;
203 dst_bidx = 0; 203 dst_bidx = 4;
204 src_cidx = data_type * fifo_level; 204 src_cidx = data_type * fifo_level;
205 dst_cidx = 0; 205 dst_cidx = 0;
206 } else { 206 } else {
@@ -223,9 +223,10 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
223 edma_set_transfer_params(prtd->asp_link[0], acnt, count, 1, 0, 223 edma_set_transfer_params(prtd->asp_link[0], acnt, count, 1, 0,
224 ASYNC); 224 ASYNC);
225 else 225 else
226 edma_set_transfer_params(prtd->asp_link[0], acnt, fifo_level, 226 edma_set_transfer_params(prtd->asp_link[0], acnt,
227 count, fifo_level, 227 fifo_level,
228 ABSYNC); 228 count, fifo_level,
229 ABSYNC);
229} 230}
230 231
231static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data) 232static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data)
diff --git a/sound/soc/davinci/davinci-vcif.c b/sound/soc/davinci/davinci-vcif.c
index 07bde2e6f84e..30587c0cdbd2 100644
--- a/sound/soc/davinci/davinci-vcif.c
+++ b/sound/soc/davinci/davinci-vcif.c
@@ -204,6 +204,10 @@ static struct snd_soc_dai_driver davinci_vcif_dai = {
204 204
205}; 205};
206 206
207static const struct snd_soc_component_driver davinci_vcif_component = {
208 .name = "davinci-vcif",
209};
210
207static int davinci_vcif_probe(struct platform_device *pdev) 211static int davinci_vcif_probe(struct platform_device *pdev)
208{ 212{
209 struct davinci_vc *davinci_vc = pdev->dev.platform_data; 213 struct davinci_vc *davinci_vc = pdev->dev.platform_data;
@@ -234,7 +238,8 @@ static int davinci_vcif_probe(struct platform_device *pdev)
234 238
235 dev_set_drvdata(&pdev->dev, davinci_vcif_dev); 239 dev_set_drvdata(&pdev->dev, davinci_vcif_dev);
236 240
237 ret = snd_soc_register_dai(&pdev->dev, &davinci_vcif_dai); 241 ret = snd_soc_register_component(&pdev->dev, &davinci_vcif_component,
242 &davinci_vcif_dai, 1);
238 if (ret != 0) { 243 if (ret != 0) {
239 dev_err(&pdev->dev, "could not register dai\n"); 244 dev_err(&pdev->dev, "could not register dai\n");
240 return ret; 245 return ret;
@@ -243,7 +248,7 @@ static int davinci_vcif_probe(struct platform_device *pdev)
243 ret = davinci_soc_platform_register(&pdev->dev); 248 ret = davinci_soc_platform_register(&pdev->dev);
244 if (ret) { 249 if (ret) {
245 dev_err(&pdev->dev, "register PCM failed: %d\n", ret); 250 dev_err(&pdev->dev, "register PCM failed: %d\n", ret);
246 snd_soc_unregister_dai(&pdev->dev); 251 snd_soc_unregister_component(&pdev->dev);
247 return ret; 252 return ret;
248 } 253 }
249 254
@@ -252,7 +257,7 @@ static int davinci_vcif_probe(struct platform_device *pdev)
252 257
253static int davinci_vcif_remove(struct platform_device *pdev) 258static int davinci_vcif_remove(struct platform_device *pdev)
254{ 259{
255 snd_soc_unregister_dai(&pdev->dev); 260 snd_soc_unregister_component(&pdev->dev);
256 davinci_soc_platform_unregister(&pdev->dev); 261 davinci_soc_platform_unregister(&pdev->dev);
257 262
258 return 0; 263 return 0;
diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c
index deb30d59965e..593a3ea12d4c 100644
--- a/sound/soc/dwc/designware_i2s.c
+++ b/sound/soc/dwc/designware_i2s.c
@@ -297,6 +297,10 @@ static struct snd_soc_dai_ops dw_i2s_dai_ops = {
297 .trigger = dw_i2s_trigger, 297 .trigger = dw_i2s_trigger,
298}; 298};
299 299
300static const struct snd_soc_component_driver dw_i2s_component = {
301 .name = "dw-i2s",
302};
303
300#ifdef CONFIG_PM 304#ifdef CONFIG_PM
301 305
302static int dw_i2s_suspend(struct snd_soc_dai *dai) 306static int dw_i2s_suspend(struct snd_soc_dai *dai)
@@ -413,7 +417,8 @@ static int dw_i2s_probe(struct platform_device *pdev)
413 417
414 dev->dev = &pdev->dev; 418 dev->dev = &pdev->dev;
415 dev_set_drvdata(&pdev->dev, dev); 419 dev_set_drvdata(&pdev->dev, dev);
416 ret = snd_soc_register_dai(&pdev->dev, dw_i2s_dai); 420 ret = snd_soc_register_component(&pdev->dev, &dw_i2s_component,
421 dw_i2s_dai, 1);
417 if (ret != 0) { 422 if (ret != 0) {
418 dev_err(&pdev->dev, "not able to register dai\n"); 423 dev_err(&pdev->dev, "not able to register dai\n");
419 goto err_set_drvdata; 424 goto err_set_drvdata;
@@ -434,7 +439,7 @@ static int dw_i2s_remove(struct platform_device *pdev)
434{ 439{
435 struct dw_i2s_dev *dev = dev_get_drvdata(&pdev->dev); 440 struct dw_i2s_dev *dev = dev_get_drvdata(&pdev->dev);
436 441
437 snd_soc_unregister_dai(&pdev->dev); 442 snd_soc_unregister_component(&pdev->dev);
438 dev_set_drvdata(&pdev->dev, NULL); 443 dev_set_drvdata(&pdev->dev, NULL);
439 444
440 clk_put(dev->clk); 445 clk_put(dev->clk);
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 3b98159d9645..3843a18d4e56 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -118,7 +118,7 @@ config SND_SOC_IMX_PCM_FIQ
118 118
119config SND_SOC_IMX_PCM_DMA 119config SND_SOC_IMX_PCM_DMA
120 bool 120 bool
121 select SND_SOC_DMAENGINE_PCM 121 select SND_SOC_GENERIC_DMAENGINE_PCM
122 select SND_SOC_IMX_PCM 122 select SND_SOC_IMX_PCM
123 123
124config SND_SOC_IMX_AUDMUX 124config SND_SOC_IMX_AUDMUX
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 7decbd9b2340..0f0bed6def9e 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -27,6 +27,7 @@
27#include <sound/pcm_params.h> 27#include <sound/pcm_params.h>
28#include <sound/initval.h> 28#include <sound/initval.h>
29#include <sound/soc.h> 29#include <sound/soc.h>
30#include <sound/dmaengine_pcm.h>
30 31
31#include "fsl_ssi.h" 32#include "fsl_ssi.h"
32#include "imx-pcm.h" 33#include "imx-pcm.h"
@@ -122,8 +123,10 @@ struct fsl_ssi_private {
122 bool ssi_on_imx; 123 bool ssi_on_imx;
123 struct clk *clk; 124 struct clk *clk;
124 struct platform_device *imx_pcm_pdev; 125 struct platform_device *imx_pcm_pdev;
125 struct imx_pcm_dma_params dma_params_tx; 126 struct snd_dmaengine_dai_dma_data dma_params_tx;
126 struct imx_pcm_dma_params dma_params_rx; 127 struct snd_dmaengine_dai_dma_data dma_params_rx;
128 struct imx_dma_data filter_data_tx;
129 struct imx_dma_data filter_data_rx;
127 130
128 struct { 131 struct {
129 unsigned int rfrc; 132 unsigned int rfrc;
@@ -422,12 +425,6 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
422 ssi_private->second_stream = substream; 425 ssi_private->second_stream = substream;
423 } 426 }
424 427
425 if (ssi_private->ssi_on_imx)
426 snd_soc_dai_set_dma_data(dai, substream,
427 (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
428 &ssi_private->dma_params_tx :
429 &ssi_private->dma_params_rx);
430
431 return 0; 428 return 0;
432} 429}
433 430
@@ -549,6 +546,18 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
549 } 546 }
550} 547}
551 548
549static int fsl_ssi_dai_probe(struct snd_soc_dai *dai)
550{
551 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai);
552
553 if (ssi_private->ssi_on_imx) {
554 dai->playback_dma_data = &ssi_private->dma_params_tx;
555 dai->capture_dma_data = &ssi_private->dma_params_rx;
556 }
557
558 return 0;
559}
560
552static const struct snd_soc_dai_ops fsl_ssi_dai_ops = { 561static const struct snd_soc_dai_ops fsl_ssi_dai_ops = {
553 .startup = fsl_ssi_startup, 562 .startup = fsl_ssi_startup,
554 .hw_params = fsl_ssi_hw_params, 563 .hw_params = fsl_ssi_hw_params,
@@ -558,6 +567,7 @@ static const struct snd_soc_dai_ops fsl_ssi_dai_ops = {
558 567
559/* Template for the CPU dai driver structure */ 568/* Template for the CPU dai driver structure */
560static struct snd_soc_dai_driver fsl_ssi_dai_template = { 569static struct snd_soc_dai_driver fsl_ssi_dai_template = {
570 .probe = fsl_ssi_dai_probe,
561 .playback = { 571 .playback = {
562 /* The SSI does not support monaural audio. */ 572 /* The SSI does not support monaural audio. */
563 .channels_min = 2, 573 .channels_min = 2,
@@ -574,6 +584,10 @@ static struct snd_soc_dai_driver fsl_ssi_dai_template = {
574 .ops = &fsl_ssi_dai_ops, 584 .ops = &fsl_ssi_dai_ops,
575}; 585};
576 586
587static const struct snd_soc_component_driver fsl_ssi_component = {
588 .name = "fsl-ssi",
589};
590
577/* Show the statistics of a flag only if its interrupt is enabled. The 591/* Show the statistics of a flag only if its interrupt is enabled. The
578 * compiler will optimze this code to a no-op if the interrupt is not 592 * compiler will optimze this code to a no-op if the interrupt is not
579 * enabled. 593 * enabled.
@@ -649,6 +663,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
649 const uint32_t *iprop; 663 const uint32_t *iprop;
650 struct resource res; 664 struct resource res;
651 char name[64]; 665 char name[64];
666 bool shared;
652 667
653 /* SSIs that are not connected on the board should have a 668 /* SSIs that are not connected on the board should have a
654 * status = "disabled" 669 * status = "disabled"
@@ -737,14 +752,18 @@ static int fsl_ssi_probe(struct platform_device *pdev)
737 * We have burstsize be "fifo_depth - 2" to match the SSI 752 * We have burstsize be "fifo_depth - 2" to match the SSI
738 * watermark setting in fsl_ssi_startup(). 753 * watermark setting in fsl_ssi_startup().
739 */ 754 */
740 ssi_private->dma_params_tx.burstsize = 755 ssi_private->dma_params_tx.maxburst =
741 ssi_private->fifo_depth - 2; 756 ssi_private->fifo_depth - 2;
742 ssi_private->dma_params_rx.burstsize = 757 ssi_private->dma_params_rx.maxburst =
743 ssi_private->fifo_depth - 2; 758 ssi_private->fifo_depth - 2;
744 ssi_private->dma_params_tx.dma_addr = 759 ssi_private->dma_params_tx.addr =
745 ssi_private->ssi_phys + offsetof(struct ccsr_ssi, stx0); 760 ssi_private->ssi_phys + offsetof(struct ccsr_ssi, stx0);
746 ssi_private->dma_params_rx.dma_addr = 761 ssi_private->dma_params_rx.addr =
747 ssi_private->ssi_phys + offsetof(struct ccsr_ssi, srx0); 762 ssi_private->ssi_phys + offsetof(struct ccsr_ssi, srx0);
763 ssi_private->dma_params_tx.filter_data =
764 &ssi_private->filter_data_tx;
765 ssi_private->dma_params_rx.filter_data =
766 &ssi_private->filter_data_rx;
748 /* 767 /*
749 * TODO: This is a temporary solution and should be changed 768 * TODO: This is a temporary solution and should be changed
750 * to use generic DMA binding later when the helplers get in. 769 * to use generic DMA binding later when the helplers get in.
@@ -755,14 +774,14 @@ static int fsl_ssi_probe(struct platform_device *pdev)
755 dev_err(&pdev->dev, "could not get dma events\n"); 774 dev_err(&pdev->dev, "could not get dma events\n");
756 goto error_clk; 775 goto error_clk;
757 } 776 }
758 ssi_private->dma_params_tx.dma = dma_events[0];
759 ssi_private->dma_params_rx.dma = dma_events[1];
760 777
761 ssi_private->dma_params_tx.shared_peripheral = 778 shared = of_device_is_compatible(of_get_parent(np),
762 of_device_is_compatible(of_get_parent(np), 779 "fsl,spba-bus");
763 "fsl,spba-bus"); 780
764 ssi_private->dma_params_rx.shared_peripheral = 781 imx_pcm_dma_params_init_data(&ssi_private->filter_data_tx,
765 ssi_private->dma_params_tx.shared_peripheral; 782 dma_events[0], shared);
783 imx_pcm_dma_params_init_data(&ssi_private->filter_data_rx,
784 dma_events[1], shared);
766 } 785 }
767 786
768 /* Initialize the the device_attribute structure */ 787 /* Initialize the the device_attribute structure */
@@ -782,7 +801,8 @@ static int fsl_ssi_probe(struct platform_device *pdev)
782 /* Register with ASoC */ 801 /* Register with ASoC */
783 dev_set_drvdata(&pdev->dev, ssi_private); 802 dev_set_drvdata(&pdev->dev, ssi_private);
784 803
785 ret = snd_soc_register_dai(&pdev->dev, &ssi_private->cpu_dai_drv); 804 ret = snd_soc_register_component(&pdev->dev, &fsl_ssi_component,
805 &ssi_private->cpu_dai_drv, 1);
786 if (ret) { 806 if (ret) {
787 dev_err(&pdev->dev, "failed to register DAI: %d\n", ret); 807 dev_err(&pdev->dev, "failed to register DAI: %d\n", ret);
788 goto error_dev; 808 goto error_dev;
@@ -835,7 +855,7 @@ done:
835error_dai: 855error_dai:
836 if (ssi_private->ssi_on_imx) 856 if (ssi_private->ssi_on_imx)
837 platform_device_unregister(ssi_private->imx_pcm_pdev); 857 platform_device_unregister(ssi_private->imx_pcm_pdev);
838 snd_soc_unregister_dai(&pdev->dev); 858 snd_soc_unregister_component(&pdev->dev);
839 859
840error_dev: 860error_dev:
841 dev_set_drvdata(&pdev->dev, NULL); 861 dev_set_drvdata(&pdev->dev, NULL);
@@ -873,7 +893,7 @@ static int fsl_ssi_remove(struct platform_device *pdev)
873 clk_disable_unprepare(ssi_private->clk); 893 clk_disable_unprepare(ssi_private->clk);
874 clk_put(ssi_private->clk); 894 clk_put(ssi_private->clk);
875 } 895 }
876 snd_soc_unregister_dai(&pdev->dev); 896 snd_soc_unregister_component(&pdev->dev);
877 device_remove_file(&pdev->dev, &ssi_private->dev_attr); 897 device_remove_file(&pdev->dev, &ssi_private->dev_attr);
878 898
879 free_irq(ssi_private->irq, ssi_private); 899 free_irq(ssi_private->irq, ssi_private);
diff --git a/sound/soc/fsl/fsl_ssi.h b/sound/soc/fsl/fsl_ssi.h
index 217300029b5b..e6b9a69e2a68 100644
--- a/sound/soc/fsl/fsl_ssi.h
+++ b/sound/soc/fsl/fsl_ssi.h
@@ -196,5 +196,13 @@ struct ccsr_ssi {
196#define CCSR_SSI_SOR_WAIT(x) (((x) & 3) << CCSR_SSI_SOR_WAIT_SHIFT) 196#define CCSR_SSI_SOR_WAIT(x) (((x) & 3) << CCSR_SSI_SOR_WAIT_SHIFT)
197#define CCSR_SSI_SOR_SYNRST 0x00000001 197#define CCSR_SSI_SOR_SYNRST 0x00000001
198 198
199#define CCSR_SSI_SACNT_FRDIV(x) (((x) & 0x3f) << 5)
200#define CCSR_SSI_SACNT_WR 0x00000010
201#define CCSR_SSI_SACNT_RD 0x00000008
202#define CCSR_SSI_SACNT_RDWR_MASK 0x00000018
203#define CCSR_SSI_SACNT_TIF 0x00000004
204#define CCSR_SSI_SACNT_FV 0x00000002
205#define CCSR_SSI_SACNT_AC97EN 0x00000001
206
199#endif 207#endif
200 208
diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c
index 3f333e5b4673..47f046a8fdab 100644
--- a/sound/soc/fsl/imx-audmux.c
+++ b/sound/soc/fsl/imx-audmux.c
@@ -262,7 +262,7 @@ static int imx_audmux_probe(struct platform_device *pdev)
262 return PTR_ERR(pinctrl); 262 return PTR_ERR(pinctrl);
263 } 263 }
264 264
265 audmux_clk = clk_get(&pdev->dev, "audmux"); 265 audmux_clk = devm_clk_get(&pdev->dev, "audmux");
266 if (IS_ERR(audmux_clk)) { 266 if (IS_ERR(audmux_clk)) {
267 dev_dbg(&pdev->dev, "cannot get clock: %ld\n", 267 dev_dbg(&pdev->dev, "cannot get clock: %ld\n",
268 PTR_ERR(audmux_clk)); 268 PTR_ERR(audmux_clk));
@@ -282,7 +282,6 @@ static int imx_audmux_remove(struct platform_device *pdev)
282{ 282{
283 if (audmux_type == IMX31_AUDMUX) 283 if (audmux_type == IMX31_AUDMUX)
284 audmux_debugfs_remove(); 284 audmux_debugfs_remove();
285 clk_put(audmux_clk);
286 285
287 return 0; 286 return 0;
288} 287}
diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c
index 500f8ce55d78..c246fb514930 100644
--- a/sound/soc/fsl/imx-pcm-dma.c
+++ b/sound/soc/fsl/imx-pcm-dma.c
@@ -11,74 +11,30 @@
11 * Free Software Foundation; either version 2 of the License, or (at your 11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version. 12 * option) any later version.
13 */ 13 */
14#include <linux/clk.h>
15#include <linux/delay.h>
16#include <linux/device.h>
17#include <linux/dma-mapping.h>
18#include <linux/init.h>
19#include <linux/interrupt.h>
20#include <linux/module.h>
21#include <linux/platform_device.h> 14#include <linux/platform_device.h>
22#include <linux/slab.h>
23#include <linux/dmaengine.h> 15#include <linux/dmaengine.h>
24#include <linux/types.h> 16#include <linux/types.h>
25 17
26#include <sound/core.h> 18#include <sound/core.h>
27#include <sound/initval.h>
28#include <sound/pcm.h> 19#include <sound/pcm.h>
29#include <sound/pcm_params.h>
30#include <sound/soc.h> 20#include <sound/soc.h>
31#include <sound/dmaengine_pcm.h> 21#include <sound/dmaengine_pcm.h>
32 22
33#include <linux/platform_data/dma-imx.h>
34
35#include "imx-pcm.h" 23#include "imx-pcm.h"
36 24
37static bool filter(struct dma_chan *chan, void *param) 25static bool filter(struct dma_chan *chan, void *param)
38{ 26{
27 struct snd_dmaengine_dai_dma_data *dma_data = param;
28
39 if (!imx_dma_is_general_purpose(chan)) 29 if (!imx_dma_is_general_purpose(chan))
40 return false; 30 return false;
41 31
42 chan->private = param; 32 chan->private = dma_data->filter_data;
43 33
44 return true; 34 return true;
45} 35}
46 36
47static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream, 37static const struct snd_pcm_hardware imx_pcm_hardware = {
48 struct snd_pcm_hw_params *params)
49{
50 struct snd_soc_pcm_runtime *rtd = substream->private_data;
51 struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
52 struct imx_pcm_dma_params *dma_params;
53 struct dma_slave_config slave_config;
54 int ret;
55
56 dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
57
58 ret = snd_hwparams_to_dma_slave_config(substream, params, &slave_config);
59 if (ret)
60 return ret;
61
62 slave_config.device_fc = false;
63
64 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
65 slave_config.dst_addr = dma_params->dma_addr;
66 slave_config.dst_maxburst = dma_params->burstsize;
67 } else {
68 slave_config.src_addr = dma_params->dma_addr;
69 slave_config.src_maxburst = dma_params->burstsize;
70 }
71
72 ret = dmaengine_slave_config(chan, &slave_config);
73 if (ret)
74 return ret;
75
76 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
77
78 return 0;
79}
80
81static struct snd_pcm_hardware snd_imx_hardware = {
82 .info = SNDRV_PCM_INFO_INTERLEAVED | 38 .info = SNDRV_PCM_INFO_INTERLEAVED |
83 SNDRV_PCM_INFO_BLOCK_TRANSFER | 39 SNDRV_PCM_INFO_BLOCK_TRANSFER |
84 SNDRV_PCM_INFO_MMAP | 40 SNDRV_PCM_INFO_MMAP |
@@ -97,64 +53,22 @@ static struct snd_pcm_hardware snd_imx_hardware = {
97 .fifo_size = 0, 53 .fifo_size = 0,
98}; 54};
99 55
100static int snd_imx_open(struct snd_pcm_substream *substream) 56static const struct snd_dmaengine_pcm_config imx_dmaengine_pcm_config = {
101{ 57 .pcm_hardware = &imx_pcm_hardware,
102 struct snd_soc_pcm_runtime *rtd = substream->private_data; 58 .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
103 struct imx_pcm_dma_params *dma_params; 59 .compat_filter_fn = filter,
104 struct imx_dma_data *dma_data; 60 .prealloc_buffer_size = IMX_SSI_DMABUF_SIZE,
105 int ret; 61};
106
107 snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
108
109 dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
110
111 dma_data = kzalloc(sizeof(*dma_data), GFP_KERNEL);
112 if (!dma_data)
113 return -ENOMEM;
114
115 dma_data->peripheral_type = dma_params->shared_peripheral ?
116 IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI;
117 dma_data->priority = DMA_PRIO_HIGH;
118 dma_data->dma_request = dma_params->dma;
119
120 ret = snd_dmaengine_pcm_open(substream, filter, dma_data);
121 if (ret) {
122 kfree(dma_data);
123 return ret;
124 }
125
126 snd_dmaengine_pcm_set_data(substream, dma_data);
127
128 return 0;
129}
130 62
131static int snd_imx_close(struct snd_pcm_substream *substream) 63int imx_pcm_dma_init(struct platform_device *pdev)
132{ 64{
133 struct imx_dma_data *dma_data = snd_dmaengine_pcm_get_data(substream); 65 return snd_dmaengine_pcm_register(&pdev->dev, &imx_dmaengine_pcm_config,
134 66 SND_DMAENGINE_PCM_FLAG_NO_RESIDUE |
135 snd_dmaengine_pcm_close(substream); 67 SND_DMAENGINE_PCM_FLAG_NO_DT |
136 kfree(dma_data); 68 SND_DMAENGINE_PCM_FLAG_COMPAT);
137
138 return 0;
139} 69}
140 70
141static struct snd_pcm_ops imx_pcm_ops = { 71void imx_pcm_dma_exit(struct platform_device *pdev)
142 .open = snd_imx_open,
143 .close = snd_imx_close,
144 .ioctl = snd_pcm_lib_ioctl,
145 .hw_params = snd_imx_pcm_hw_params,
146 .trigger = snd_dmaengine_pcm_trigger,
147 .pointer = snd_dmaengine_pcm_pointer_no_residue,
148 .mmap = snd_imx_pcm_mmap,
149};
150
151static struct snd_soc_platform_driver imx_soc_platform_mx2 = {
152 .ops = &imx_pcm_ops,
153 .pcm_new = imx_pcm_new,
154 .pcm_free = imx_pcm_free,
155};
156
157int imx_pcm_dma_init(struct platform_device *pdev)
158{ 72{
159 return snd_soc_register_platform(&pdev->dev, &imx_soc_platform_mx2); 73 snd_dmaengine_pcm_unregister(&pdev->dev);
160} 74}
diff --git a/sound/soc/fsl/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c
index 920f945cb2f4..670b96b0ce2f 100644
--- a/sound/soc/fsl/imx-pcm-fiq.c
+++ b/sound/soc/fsl/imx-pcm-fiq.c
@@ -34,7 +34,7 @@
34#include "imx-ssi.h" 34#include "imx-ssi.h"
35 35
36struct imx_pcm_runtime_data { 36struct imx_pcm_runtime_data {
37 int period; 37 unsigned int period;
38 int periods; 38 int periods;
39 unsigned long offset; 39 unsigned long offset;
40 unsigned long last_offset; 40 unsigned long last_offset;
@@ -299,8 +299,8 @@ int imx_pcm_fiq_init(struct platform_device *pdev)
299 299
300 imx_ssi_fiq_base = (unsigned long)ssi->base; 300 imx_ssi_fiq_base = (unsigned long)ssi->base;
301 301
302 ssi->dma_params_tx.burstsize = 4; 302 ssi->dma_params_tx.maxburst = 4;
303 ssi->dma_params_rx.burstsize = 6; 303 ssi->dma_params_rx.maxburst = 6;
304 304
305 ret = snd_soc_register_platform(&pdev->dev, &imx_soc_platform_fiq); 305 ret = snd_soc_register_platform(&pdev->dev, &imx_soc_platform_fiq);
306 if (ret) 306 if (ret)
diff --git a/sound/soc/fsl/imx-pcm.c b/sound/soc/fsl/imx-pcm.c
index 0d0625bfcb65..c49896442d8e 100644
--- a/sound/soc/fsl/imx-pcm.c
+++ b/sound/soc/fsl/imx-pcm.c
@@ -114,7 +114,11 @@ static int imx_pcm_probe(struct platform_device *pdev)
114 114
115static int imx_pcm_remove(struct platform_device *pdev) 115static int imx_pcm_remove(struct platform_device *pdev)
116{ 116{
117 snd_soc_unregister_platform(&pdev->dev); 117 if (strcmp(pdev->id_entry->name, "imx-fiq-pcm-audio") == 0)
118 snd_soc_unregister_platform(&pdev->dev);
119 else
120 imx_pcm_dma_exit(pdev);
121
118 return 0; 122 return 0;
119} 123}
120 124
diff --git a/sound/soc/fsl/imx-pcm.h b/sound/soc/fsl/imx-pcm.h
index 5ae13a13a353..b7fa0d75c687 100644
--- a/sound/soc/fsl/imx-pcm.h
+++ b/sound/soc/fsl/imx-pcm.h
@@ -13,17 +13,24 @@
13#ifndef _IMX_PCM_H 13#ifndef _IMX_PCM_H
14#define _IMX_PCM_H 14#define _IMX_PCM_H
15 15
16#include <linux/platform_data/dma-imx.h>
17
16/* 18/*
17 * Do not change this as the FIQ handler depends on this size 19 * Do not change this as the FIQ handler depends on this size
18 */ 20 */
19#define IMX_SSI_DMABUF_SIZE (64 * 1024) 21#define IMX_SSI_DMABUF_SIZE (64 * 1024)
20 22
21struct imx_pcm_dma_params { 23static inline void
22 int dma; 24imx_pcm_dma_params_init_data(struct imx_dma_data *dma_data,
23 unsigned long dma_addr; 25 int dma, bool shared)
24 int burstsize; 26{
25 bool shared_peripheral; /* The peripheral is on SPBA bus */ 27 dma_data->dma_request = dma;
26}; 28 dma_data->priority = DMA_PRIO_HIGH;
29 if (shared)
30 dma_data->peripheral_type = IMX_DMATYPE_SSI_SP;
31 else
32 dma_data->peripheral_type = IMX_DMATYPE_SSI;
33}
27 34
28int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, 35int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
29 struct vm_area_struct *vma); 36 struct vm_area_struct *vma);
@@ -32,11 +39,16 @@ void imx_pcm_free(struct snd_pcm *pcm);
32 39
33#ifdef CONFIG_SND_SOC_IMX_PCM_DMA 40#ifdef CONFIG_SND_SOC_IMX_PCM_DMA
34int imx_pcm_dma_init(struct platform_device *pdev); 41int imx_pcm_dma_init(struct platform_device *pdev);
42void imx_pcm_dma_exit(struct platform_device *pdev);
35#else 43#else
36static inline int imx_pcm_dma_init(struct platform_device *pdev) 44static inline int imx_pcm_dma_init(struct platform_device *pdev)
37{ 45{
38 return -ENODEV; 46 return -ENODEV;
39} 47}
48
49static inline void imx_pcm_dma_exit(struct platform_device *pdev)
50{
51}
40#endif 52#endif
41 53
42#ifdef CONFIG_SND_SOC_IMX_PCM_FIQ 54#ifdef CONFIG_SND_SOC_IMX_PCM_FIQ
diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c
index 424347e9b2d7..9584e78858df 100644
--- a/sound/soc/fsl/imx-sgtl5000.c
+++ b/sound/soc/fsl/imx-sgtl5000.c
@@ -148,7 +148,7 @@ static int imx_sgtl5000_probe(struct platform_device *pdev)
148 data->dai.stream_name = "HiFi"; 148 data->dai.stream_name = "HiFi";
149 data->dai.codec_dai_name = "sgtl5000"; 149 data->dai.codec_dai_name = "sgtl5000";
150 data->dai.codec_of_node = codec_np; 150 data->dai.codec_of_node = codec_np;
151 data->dai.cpu_dai_name = dev_name(&ssi_pdev->dev); 151 data->dai.cpu_of_node = ssi_np;
152 data->dai.platform_name = "imx-pcm-audio"; 152 data->dai.platform_name = "imx-pcm-audio";
153 data->dai.init = &imx_sgtl5000_dai_init; 153 data->dai.init = &imx_sgtl5000_dai_init;
154 data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 154 data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c
index 810c7eeb7b03..902fab02b851 100644
--- a/sound/soc/fsl/imx-ssi.c
+++ b/sound/soc/fsl/imx-ssi.c
@@ -232,23 +232,6 @@ static int imx_ssi_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
232 return 0; 232 return 0;
233} 233}
234 234
235static int imx_ssi_startup(struct snd_pcm_substream *substream,
236 struct snd_soc_dai *cpu_dai)
237{
238 struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
239 struct imx_pcm_dma_params *dma_data;
240
241 /* Tx/Rx config */
242 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
243 dma_data = &ssi->dma_params_tx;
244 else
245 dma_data = &ssi->dma_params_rx;
246
247 snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
248
249 return 0;
250}
251
252/* 235/*
253 * Should only be called when port is inactive (i.e. SSIEN = 0), 236 * Should only be called when port is inactive (i.e. SSIEN = 0),
254 * although can be called multiple times by upper layers. 237 * although can be called multiple times by upper layers.
@@ -353,7 +336,6 @@ static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
353} 336}
354 337
355static const struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = { 338static const struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = {
356 .startup = imx_ssi_startup,
357 .hw_params = imx_ssi_hw_params, 339 .hw_params = imx_ssi_hw_params,
358 .set_fmt = imx_ssi_set_dai_fmt, 340 .set_fmt = imx_ssi_set_dai_fmt,
359 .set_clkdiv = imx_ssi_set_dai_clkdiv, 341 .set_clkdiv = imx_ssi_set_dai_clkdiv,
@@ -369,10 +351,14 @@ static int imx_ssi_dai_probe(struct snd_soc_dai *dai)
369 351
370 snd_soc_dai_set_drvdata(dai, ssi); 352 snd_soc_dai_set_drvdata(dai, ssi);
371 353
372 val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.burstsize) | 354 val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.maxburst) |
373 SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize); 355 SSI_SFCSR_RFWM0(ssi->dma_params_rx.maxburst);
374 writel(val, ssi->base + SSI_SFCSR); 356 writel(val, ssi->base + SSI_SFCSR);
375 357
358 /* Tx/Rx config */
359 dai->playback_dma_data = &ssi->dma_params_tx;
360 dai->capture_dma_data = &ssi->dma_params_rx;
361
376 return 0; 362 return 0;
377} 363}
378 364
@@ -400,7 +386,7 @@ static struct snd_soc_dai_driver imx_ac97_dai = {
400 .stream_name = "AC97 Playback", 386 .stream_name = "AC97 Playback",
401 .channels_min = 2, 387 .channels_min = 2,
402 .channels_max = 2, 388 .channels_max = 2,
403 .rates = SNDRV_PCM_RATE_48000, 389 .rates = SNDRV_PCM_RATE_8000_48000,
404 .formats = SNDRV_PCM_FMTBIT_S16_LE, 390 .formats = SNDRV_PCM_FMTBIT_S16_LE,
405 }, 391 },
406 .capture = { 392 .capture = {
@@ -413,6 +399,10 @@ static struct snd_soc_dai_driver imx_ac97_dai = {
413 .ops = &imx_ssi_pcm_dai_ops, 399 .ops = &imx_ssi_pcm_dai_ops,
414}; 400};
415 401
402static const struct snd_soc_component_driver imx_component = {
403 .name = DRV_NAME,
404};
405
416static void setup_channel_to_ac97(struct imx_ssi *imx_ssi) 406static void setup_channel_to_ac97(struct imx_ssi *imx_ssi)
417{ 407{
418 void __iomem *base = imx_ssi->base; 408 void __iomem *base = imx_ssi->base;
@@ -575,23 +565,31 @@ static int imx_ssi_probe(struct platform_device *pdev)
575 565
576 writel(0x0, ssi->base + SSI_SIER); 566 writel(0x0, ssi->base + SSI_SIER);
577 567
578 ssi->dma_params_rx.dma_addr = res->start + SSI_SRX0; 568 ssi->dma_params_rx.addr = res->start + SSI_SRX0;
579 ssi->dma_params_tx.dma_addr = res->start + SSI_STX0; 569 ssi->dma_params_tx.addr = res->start + SSI_STX0;
570
571 ssi->dma_params_tx.maxburst = 6;
572 ssi->dma_params_rx.maxburst = 4;
580 573
581 ssi->dma_params_tx.burstsize = 6; 574 ssi->dma_params_tx.filter_data = &ssi->filter_data_tx;
582 ssi->dma_params_rx.burstsize = 4; 575 ssi->dma_params_rx.filter_data = &ssi->filter_data_rx;
583 576
584 res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0"); 577 res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0");
585 if (res) 578 if (res) {
586 ssi->dma_params_tx.dma = res->start; 579 imx_pcm_dma_params_init_data(&ssi->filter_data_tx, res->start,
580 false);
581 }
587 582
588 res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx0"); 583 res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx0");
589 if (res) 584 if (res) {
590 ssi->dma_params_rx.dma = res->start; 585 imx_pcm_dma_params_init_data(&ssi->filter_data_rx, res->start,
586 false);
587 }
591 588
592 platform_set_drvdata(pdev, ssi); 589 platform_set_drvdata(pdev, ssi);
593 590
594 ret = snd_soc_register_dai(&pdev->dev, dai); 591 ret = snd_soc_register_component(&pdev->dev, &imx_component,
592 dai, 1);
595 if (ret) { 593 if (ret) {
596 dev_err(&pdev->dev, "register DAI failed\n"); 594 dev_err(&pdev->dev, "register DAI failed\n");
597 goto failed_register; 595 goto failed_register;
@@ -632,7 +630,7 @@ failed_pdev_alloc:
632failed_pdev_fiq_add: 630failed_pdev_fiq_add:
633 platform_device_put(ssi->soc_platform_pdev_fiq); 631 platform_device_put(ssi->soc_platform_pdev_fiq);
634failed_pdev_fiq_alloc: 632failed_pdev_fiq_alloc:
635 snd_soc_unregister_dai(&pdev->dev); 633 snd_soc_unregister_component(&pdev->dev);
636failed_register: 634failed_register:
637 release_mem_region(res->start, resource_size(res)); 635 release_mem_region(res->start, resource_size(res));
638failed_get_resource: 636failed_get_resource:
@@ -650,7 +648,7 @@ static int imx_ssi_remove(struct platform_device *pdev)
650 platform_device_unregister(ssi->soc_platform_pdev); 648 platform_device_unregister(ssi->soc_platform_pdev);
651 platform_device_unregister(ssi->soc_platform_pdev_fiq); 649 platform_device_unregister(ssi->soc_platform_pdev_fiq);
652 650
653 snd_soc_unregister_dai(&pdev->dev); 651 snd_soc_unregister_component(&pdev->dev);
654 652
655 if (ssi->flags & IMX_SSI_USE_AC97) 653 if (ssi->flags & IMX_SSI_USE_AC97)
656 ac97_ssi = NULL; 654 ac97_ssi = NULL;
diff --git a/sound/soc/fsl/imx-ssi.h b/sound/soc/fsl/imx-ssi.h
index dc114bdedce5..bb6b3dbb13fd 100644
--- a/sound/soc/fsl/imx-ssi.h
+++ b/sound/soc/fsl/imx-ssi.h
@@ -187,6 +187,7 @@
187 187
188#include <linux/dmaengine.h> 188#include <linux/dmaengine.h>
189#include <linux/platform_data/dma-imx.h> 189#include <linux/platform_data/dma-imx.h>
190#include <sound/dmaengine_pcm.h>
190#include "imx-pcm.h" 191#include "imx-pcm.h"
191 192
192struct imx_ssi { 193struct imx_ssi {
@@ -204,8 +205,10 @@ struct imx_ssi {
204 void (*ac97_reset) (struct snd_ac97 *ac97); 205 void (*ac97_reset) (struct snd_ac97 *ac97);
205 void (*ac97_warm_reset)(struct snd_ac97 *ac97); 206 void (*ac97_warm_reset)(struct snd_ac97 *ac97);
206 207
207 struct imx_pcm_dma_params dma_params_rx; 208 struct snd_dmaengine_dai_dma_data dma_params_rx;
208 struct imx_pcm_dma_params dma_params_tx; 209 struct snd_dmaengine_dai_dma_data dma_params_tx;
210 struct imx_dma_data filter_data_tx;
211 struct imx_dma_data filter_data_rx;
209 212
210 int enabled; 213 int enabled;
211 214
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c
index a4aec0488dd3..4141b35ef0bb 100644
--- a/sound/soc/fsl/mpc5200_psc_ac97.c
+++ b/sound/soc/fsl/mpc5200_psc_ac97.c
@@ -270,6 +270,9 @@ static struct snd_soc_dai_driver psc_ac97_dai[] = {
270 .ops = &psc_ac97_digital_ops, 270 .ops = &psc_ac97_digital_ops,
271} }; 271} };
272 272
273static const struct snd_soc_component_driver psc_ac97_component = {
274 .name = DRV_NAME,
275};
273 276
274 277
275/* --------------------------------------------------------------------- 278/* ---------------------------------------------------------------------
@@ -287,7 +290,8 @@ static int psc_ac97_of_probe(struct platform_device *op)
287 if (rc != 0) 290 if (rc != 0)
288 return rc; 291 return rc;
289 292
290 rc = snd_soc_register_dais(&op->dev, psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai)); 293 rc = snd_soc_register_component(&op->dev, &psc_ac97_component,
294 psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai));
291 if (rc != 0) { 295 if (rc != 0) {
292 dev_err(&op->dev, "Failed to register DAI\n"); 296 dev_err(&op->dev, "Failed to register DAI\n");
293 return rc; 297 return rc;
@@ -313,7 +317,7 @@ static int psc_ac97_of_probe(struct platform_device *op)
313static int psc_ac97_of_remove(struct platform_device *op) 317static int psc_ac97_of_remove(struct platform_device *op)
314{ 318{
315 mpc5200_audio_dma_destroy(op); 319 mpc5200_audio_dma_destroy(op);
316 snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_ac97_dai)); 320 snd_soc_unregister_component(&op->dev);
317 return 0; 321 return 0;
318} 322}
319 323
diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c
index b95b966f25a0..f4efaadb80a2 100644
--- a/sound/soc/fsl/mpc5200_psc_i2s.c
+++ b/sound/soc/fsl/mpc5200_psc_i2s.c
@@ -148,6 +148,10 @@ static struct snd_soc_dai_driver psc_i2s_dai[] = {{
148 .ops = &psc_i2s_dai_ops, 148 .ops = &psc_i2s_dai_ops,
149} }; 149} };
150 150
151static const struct snd_soc_component_driver psc_i2s_component = {
152 .name = "mpc5200-i2s",
153};
154
151/* --------------------------------------------------------------------- 155/* ---------------------------------------------------------------------
152 * OF platform bus binding code: 156 * OF platform bus binding code:
153 * - Probe/remove operations 157 * - Probe/remove operations
@@ -163,7 +167,8 @@ static int psc_i2s_of_probe(struct platform_device *op)
163 if (rc != 0) 167 if (rc != 0)
164 return rc; 168 return rc;
165 169
166 rc = snd_soc_register_dais(&op->dev, psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai)); 170 rc = snd_soc_register_component(&op->dev, &psc_i2s_component,
171 psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai));
167 if (rc != 0) { 172 if (rc != 0) {
168 pr_err("Failed to register DAI\n"); 173 pr_err("Failed to register DAI\n");
169 return rc; 174 return rc;
@@ -208,7 +213,7 @@ static int psc_i2s_of_probe(struct platform_device *op)
208static int psc_i2s_of_remove(struct platform_device *op) 213static int psc_i2s_of_remove(struct platform_device *op)
209{ 214{
210 mpc5200_audio_dma_destroy(op); 215 mpc5200_audio_dma_destroy(op);
211 snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_i2s_dai)); 216 snd_soc_unregister_component(&op->dev);
212 return 0; 217 return 0;
213} 218}
214 219
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c
index 6cef491f4823..9a126441c5f3 100644
--- a/sound/soc/jz4740/jz4740-i2s.c
+++ b/sound/soc/jz4740/jz4740-i2s.c
@@ -425,6 +425,10 @@ static struct snd_soc_dai_driver jz4740_i2s_dai = {
425 .resume = jz4740_i2s_resume, 425 .resume = jz4740_i2s_resume,
426}; 426};
427 427
428static const struct snd_soc_component_driver jz4740_i2s_component = {
429 .name = "jz4740-i2s",
430};
431
428static int jz4740_i2s_dev_probe(struct platform_device *pdev) 432static int jz4740_i2s_dev_probe(struct platform_device *pdev)
429{ 433{
430 struct jz4740_i2s *i2s; 434 struct jz4740_i2s *i2s;
@@ -469,7 +473,8 @@ static int jz4740_i2s_dev_probe(struct platform_device *pdev)
469 } 473 }
470 474
471 platform_set_drvdata(pdev, i2s); 475 platform_set_drvdata(pdev, i2s);
472 ret = snd_soc_register_dai(&pdev->dev, &jz4740_i2s_dai); 476 ret = snd_soc_register_component(&pdev->dev, &jz4740_i2s_component,
477 &jz4740_i2s_dai, 1);
473 478
474 if (ret) { 479 if (ret) {
475 dev_err(&pdev->dev, "Failed to register DAI\n"); 480 dev_err(&pdev->dev, "Failed to register DAI\n");
@@ -496,7 +501,7 @@ static int jz4740_i2s_dev_remove(struct platform_device *pdev)
496{ 501{
497 struct jz4740_i2s *i2s = platform_get_drvdata(pdev); 502 struct jz4740_i2s *i2s = platform_get_drvdata(pdev);
498 503
499 snd_soc_unregister_dai(&pdev->dev); 504 snd_soc_unregister_component(&pdev->dev);
500 505
501 clk_put(i2s->clk_i2s); 506 clk_put(i2s->clk_i2s);
502 clk_put(i2s->clk_aic); 507 clk_put(i2s->clk_aic);
diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c
index c74c89065493..befe68f59285 100644
--- a/sound/soc/kirkwood/kirkwood-i2s.c
+++ b/sound/soc/kirkwood/kirkwood-i2s.c
@@ -451,6 +451,10 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk = {
451 .ops = &kirkwood_i2s_dai_ops, 451 .ops = &kirkwood_i2s_dai_ops,
452}; 452};
453 453
454static const struct snd_soc_component_driver kirkwood_i2s_component = {
455 .name = DRV_NAME,
456};
457
454static int kirkwood_i2s_dev_probe(struct platform_device *pdev) 458static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
455{ 459{
456 struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data; 460 struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data;
@@ -524,10 +528,11 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
524 priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_128; 528 priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_128;
525 } 529 }
526 530
527 err = snd_soc_register_dai(&pdev->dev, soc_dai); 531 err = snd_soc_register_component(&pdev->dev, &kirkwood_i2s_component,
532 soc_dai, 1);
528 if (!err) 533 if (!err)
529 return 0; 534 return 0;
530 dev_err(&pdev->dev, "snd_soc_register_dai failed\n"); 535 dev_err(&pdev->dev, "snd_soc_register_component failed\n");
531 536
532 if (!IS_ERR(priv->extclk)) { 537 if (!IS_ERR(priv->extclk)) {
533 clk_disable_unprepare(priv->extclk); 538 clk_disable_unprepare(priv->extclk);
@@ -542,7 +547,7 @@ static int kirkwood_i2s_dev_remove(struct platform_device *pdev)
542{ 547{
543 struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev); 548 struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev);
544 549
545 snd_soc_unregister_dai(&pdev->dev); 550 snd_soc_unregister_component(&pdev->dev);
546 551
547 if (!IS_ERR(priv->extclk)) { 552 if (!IS_ERR(priv->extclk)) {
548 clk_disable_unprepare(priv->extclk); 553 clk_disable_unprepare(priv->extclk);
diff --git a/sound/soc/mid-x86/sst_platform.c b/sound/soc/mid-x86/sst_platform.c
index a263cbed8624..392fc0b8f5b8 100644
--- a/sound/soc/mid-x86/sst_platform.c
+++ b/sound/soc/mid-x86/sst_platform.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * sst_platform.c - Intel MID Platform driver 2 * sst_platform.c - Intel MID Platform driver
3 * 3 *
4 * Copyright (C) 2010-2012 Intel Corp 4 * Copyright (C) 2010-2013 Intel Corp
5 * Author: Vinod Koul <vinod.koul@intel.com> 5 * Author: Vinod Koul <vinod.koul@intel.com>
6 * Author: Harsha Priya <priya.harsha@intel.com> 6 * Author: Harsha Priya <priya.harsha@intel.com>
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -165,6 +165,10 @@ static struct snd_soc_dai_driver sst_platform_dai[] = {
165}, 165},
166}; 166};
167 167
168static const struct snd_soc_component_driver sst_component = {
169 .name = "sst",
170};
171
168/* helper functions */ 172/* helper functions */
169static inline void sst_set_stream_status(struct sst_runtime_stream *stream, 173static inline void sst_set_stream_status(struct sst_runtime_stream *stream,
170 int state) 174 int state)
@@ -652,11 +656,21 @@ static int sst_platform_compr_get_codec_caps(struct snd_compr_stream *cstream,
652 return stream->compr_ops->get_codec_caps(codec); 656 return stream->compr_ops->get_codec_caps(codec);
653} 657}
654 658
659static int sst_platform_compr_set_metadata(struct snd_compr_stream *cstream,
660 struct snd_compr_metadata *metadata)
661{
662 struct sst_runtime_stream *stream =
663 cstream->runtime->private_data;
664
665 return stream->compr_ops->set_metadata(stream->id, metadata);
666}
667
655static struct snd_compr_ops sst_platform_compr_ops = { 668static struct snd_compr_ops sst_platform_compr_ops = {
656 669
657 .open = sst_platform_compr_open, 670 .open = sst_platform_compr_open,
658 .free = sst_platform_compr_free, 671 .free = sst_platform_compr_free,
659 .set_params = sst_platform_compr_set_params, 672 .set_params = sst_platform_compr_set_params,
673 .set_metadata = sst_platform_compr_set_metadata,
660 .trigger = sst_platform_compr_trigger, 674 .trigger = sst_platform_compr_trigger,
661 .pointer = sst_platform_compr_pointer, 675 .pointer = sst_platform_compr_pointer,
662 .ack = sst_platform_compr_ack, 676 .ack = sst_platform_compr_ack,
@@ -683,7 +697,7 @@ static int sst_platform_probe(struct platform_device *pdev)
683 return ret; 697 return ret;
684 } 698 }
685 699
686 ret = snd_soc_register_dais(&pdev->dev, 700 ret = snd_soc_register_component(&pdev->dev, &sst_component,
687 sst_platform_dai, ARRAY_SIZE(sst_platform_dai)); 701 sst_platform_dai, ARRAY_SIZE(sst_platform_dai));
688 if (ret) { 702 if (ret) {
689 pr_err("registering cpu dais failed\n"); 703 pr_err("registering cpu dais failed\n");
@@ -695,7 +709,7 @@ static int sst_platform_probe(struct platform_device *pdev)
695static int sst_platform_remove(struct platform_device *pdev) 709static int sst_platform_remove(struct platform_device *pdev)
696{ 710{
697 711
698 snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(sst_platform_dai)); 712 snd_soc_unregister_component(&pdev->dev);
699 snd_soc_unregister_platform(&pdev->dev); 713 snd_soc_unregister_platform(&pdev->dev);
700 pr_debug("sst_platform_remove success\n"); 714 pr_debug("sst_platform_remove success\n");
701 return 0; 715 return 0;
diff --git a/sound/soc/mid-x86/sst_platform.h b/sound/soc/mid-x86/sst_platform.h
index d61c5d514ffa..cacc9066ec52 100644
--- a/sound/soc/mid-x86/sst_platform.h
+++ b/sound/soc/mid-x86/sst_platform.h
@@ -124,6 +124,8 @@ struct compress_sst_ops {
124 int (*close) (unsigned int str_id); 124 int (*close) (unsigned int str_id);
125 int (*get_caps) (struct snd_compr_caps *caps); 125 int (*get_caps) (struct snd_compr_caps *caps);
126 int (*get_codec_caps) (struct snd_compr_codec_caps *codec); 126 int (*get_codec_caps) (struct snd_compr_codec_caps *codec);
127 int (*set_metadata) (unsigned int str_id,
128 struct snd_compr_metadata *mdata);
127 129
128}; 130};
129 131
diff --git a/sound/soc/mxs/Kconfig b/sound/soc/mxs/Kconfig
index b6fa77678d97..78d321cbe8b4 100644
--- a/sound/soc/mxs/Kconfig
+++ b/sound/soc/mxs/Kconfig
@@ -1,7 +1,7 @@
1menuconfig SND_MXS_SOC 1menuconfig SND_MXS_SOC
2 tristate "SoC Audio for Freescale MXS CPUs" 2 tristate "SoC Audio for Freescale MXS CPUs"
3 depends on ARCH_MXS 3 depends on ARCH_MXS
4 select SND_SOC_DMAENGINE_PCM 4 select SND_SOC_GENERIC_DMAENGINE_PCM
5 help 5 help
6 Say Y or M if you want to add support for codecs attached to 6 Say Y or M if you want to add support for codecs attached to
7 the MXS SAIF interface. 7 the MXS SAIF interface.
diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c
index 564b5b60319d..b41fffc056fb 100644
--- a/sound/soc/mxs/mxs-pcm.c
+++ b/sound/soc/mxs/mxs-pcm.c
@@ -18,38 +18,24 @@
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */ 19 */
20 20
21#include <linux/clk.h>
22#include <linux/delay.h>
23#include <linux/device.h> 21#include <linux/device.h>
24#include <linux/dma-mapping.h>
25#include <linux/init.h> 22#include <linux/init.h>
26#include <linux/interrupt.h>
27#include <linux/module.h> 23#include <linux/module.h>
28#include <linux/platform_device.h>
29#include <linux/slab.h>
30#include <linux/dmaengine.h>
31#include <linux/fsl/mxs-dma.h>
32 24
33#include <sound/core.h> 25#include <sound/core.h>
34#include <sound/initval.h>
35#include <sound/pcm.h> 26#include <sound/pcm.h>
36#include <sound/pcm_params.h>
37#include <sound/soc.h> 27#include <sound/soc.h>
38#include <sound/dmaengine_pcm.h> 28#include <sound/dmaengine_pcm.h>
39 29
40#include "mxs-pcm.h" 30#include "mxs-pcm.h"
41 31
42struct mxs_pcm_dma_data { 32static const struct snd_pcm_hardware snd_mxs_hardware = {
43 struct mxs_dma_data dma_data;
44 struct mxs_pcm_dma_params *dma_params;
45};
46
47static struct snd_pcm_hardware snd_mxs_hardware = {
48 .info = SNDRV_PCM_INFO_MMAP | 33 .info = SNDRV_PCM_INFO_MMAP |
49 SNDRV_PCM_INFO_MMAP_VALID | 34 SNDRV_PCM_INFO_MMAP_VALID |
50 SNDRV_PCM_INFO_PAUSE | 35 SNDRV_PCM_INFO_PAUSE |
51 SNDRV_PCM_INFO_RESUME | 36 SNDRV_PCM_INFO_RESUME |
52 SNDRV_PCM_INFO_INTERLEAVED, 37 SNDRV_PCM_INFO_INTERLEAVED |
38 SNDRV_PCM_INFO_HALF_DUPLEX,
53 .formats = SNDRV_PCM_FMTBIT_S16_LE | 39 .formats = SNDRV_PCM_FMTBIT_S16_LE |
54 SNDRV_PCM_FMTBIT_S20_3LE | 40 SNDRV_PCM_FMTBIT_S20_3LE |
55 SNDRV_PCM_FMTBIT_S24_LE, 41 SNDRV_PCM_FMTBIT_S24_LE,
@@ -61,13 +47,11 @@ static struct snd_pcm_hardware snd_mxs_hardware = {
61 .periods_max = 52, 47 .periods_max = 52,
62 .buffer_bytes_max = 64 * 1024, 48 .buffer_bytes_max = 64 * 1024,
63 .fifo_size = 32, 49 .fifo_size = 32,
64
65}; 50};
66 51
67static bool filter(struct dma_chan *chan, void *param) 52static bool filter(struct dma_chan *chan, void *param)
68{ 53{
69 struct mxs_pcm_dma_data *pcm_dma_data = param; 54 struct mxs_pcm_dma_params *dma_params = param;
70 struct mxs_pcm_dma_params *dma_params = pcm_dma_data->dma_params;
71 55
72 if (!mxs_dma_is_apbx(chan)) 56 if (!mxs_dma_is_apbx(chan))
73 return false; 57 return false;
@@ -75,160 +59,30 @@ static bool filter(struct dma_chan *chan, void *param)
75 if (chan->chan_id != dma_params->chan_num) 59 if (chan->chan_id != dma_params->chan_num)
76 return false; 60 return false;
77 61
78 chan->private = &pcm_dma_data->dma_data; 62 chan->private = &dma_params->dma_data;
79 63
80 return true; 64 return true;
81} 65}
82 66
83static int snd_mxs_pcm_hw_params(struct snd_pcm_substream *substream, 67static const struct snd_dmaengine_pcm_config mxs_dmaengine_pcm_config = {
84 struct snd_pcm_hw_params *params) 68 .pcm_hardware = &snd_mxs_hardware,
85{ 69 .compat_filter_fn = filter,
86 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 70 .prealloc_buffer_size = 64 * 1024,
87
88 return 0;
89}
90
91static int snd_mxs_open(struct snd_pcm_substream *substream)
92{
93 struct snd_soc_pcm_runtime *rtd = substream->private_data;
94 struct mxs_pcm_dma_data *pcm_dma_data;
95 int ret;
96
97 pcm_dma_data = kzalloc(sizeof(*pcm_dma_data), GFP_KERNEL);
98 if (pcm_dma_data == NULL)
99 return -ENOMEM;
100
101 pcm_dma_data->dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
102 pcm_dma_data->dma_data.chan_irq = pcm_dma_data->dma_params->chan_irq;
103
104 ret = snd_dmaengine_pcm_open(substream, filter, pcm_dma_data);
105 if (ret) {
106 kfree(pcm_dma_data);
107 return ret;
108 }
109
110 snd_soc_set_runtime_hwparams(substream, &snd_mxs_hardware);
111
112 snd_dmaengine_pcm_set_data(substream, pcm_dma_data);
113
114 return 0;
115}
116
117static int snd_mxs_close(struct snd_pcm_substream *substream)
118{
119 struct mxs_pcm_dma_data *pcm_dma_data = snd_dmaengine_pcm_get_data(substream);
120
121 snd_dmaengine_pcm_close(substream);
122 kfree(pcm_dma_data);
123
124 return 0;
125}
126
127static int snd_mxs_pcm_mmap(struct snd_pcm_substream *substream,
128 struct vm_area_struct *vma)
129{
130 struct snd_pcm_runtime *runtime = substream->runtime;
131
132 return dma_mmap_writecombine(substream->pcm->card->dev, vma,
133 runtime->dma_area,
134 runtime->dma_addr,
135 runtime->dma_bytes);
136}
137
138static struct snd_pcm_ops mxs_pcm_ops = {
139 .open = snd_mxs_open,
140 .close = snd_mxs_close,
141 .ioctl = snd_pcm_lib_ioctl,
142 .hw_params = snd_mxs_pcm_hw_params,
143 .trigger = snd_dmaengine_pcm_trigger,
144 .pointer = snd_dmaengine_pcm_pointer_no_residue,
145 .mmap = snd_mxs_pcm_mmap,
146};
147
148static int mxs_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
149{
150 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
151 struct snd_dma_buffer *buf = &substream->dma_buffer;
152 size_t size = snd_mxs_hardware.buffer_bytes_max;
153
154 buf->dev.type = SNDRV_DMA_TYPE_DEV;
155 buf->dev.dev = pcm->card->dev;
156 buf->private_data = NULL;
157 buf->area = dma_alloc_writecombine(pcm->card->dev, size,
158 &buf->addr, GFP_KERNEL);
159 if (!buf->area)
160 return -ENOMEM;
161 buf->bytes = size;
162
163 return 0;
164}
165
166static u64 mxs_pcm_dmamask = DMA_BIT_MASK(32);
167static int mxs_pcm_new(struct snd_soc_pcm_runtime *rtd)
168{
169 struct snd_card *card = rtd->card->snd_card;
170 struct snd_pcm *pcm = rtd->pcm;
171 int ret = 0;
172
173 if (!card->dev->dma_mask)
174 card->dev->dma_mask = &mxs_pcm_dmamask;
175 if (!card->dev->coherent_dma_mask)
176 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
177
178 if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
179 ret = mxs_pcm_preallocate_dma_buffer(pcm,
180 SNDRV_PCM_STREAM_PLAYBACK);
181 if (ret)
182 goto out;
183 }
184
185 if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
186 ret = mxs_pcm_preallocate_dma_buffer(pcm,
187 SNDRV_PCM_STREAM_CAPTURE);
188 if (ret)
189 goto out;
190 }
191
192out:
193 return ret;
194}
195
196static void mxs_pcm_free(struct snd_pcm *pcm)
197{
198 struct snd_pcm_substream *substream;
199 struct snd_dma_buffer *buf;
200 int stream;
201
202 for (stream = 0; stream < 2; stream++) {
203 substream = pcm->streams[stream].substream;
204 if (!substream)
205 continue;
206
207 buf = &substream->dma_buffer;
208 if (!buf->area)
209 continue;
210
211 dma_free_writecombine(pcm->card->dev, buf->bytes,
212 buf->area, buf->addr);
213 buf->area = NULL;
214 }
215}
216
217static struct snd_soc_platform_driver mxs_soc_platform = {
218 .ops = &mxs_pcm_ops,
219 .pcm_new = mxs_pcm_new,
220 .pcm_free = mxs_pcm_free,
221}; 71};
222 72
223int mxs_pcm_platform_register(struct device *dev) 73int mxs_pcm_platform_register(struct device *dev)
224{ 74{
225 return snd_soc_register_platform(dev, &mxs_soc_platform); 75 return snd_dmaengine_pcm_register(dev, &mxs_dmaengine_pcm_config,
76 SND_DMAENGINE_PCM_FLAG_NO_RESIDUE |
77 SND_DMAENGINE_PCM_FLAG_NO_DT |
78 SND_DMAENGINE_PCM_FLAG_COMPAT |
79 SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX);
226} 80}
227EXPORT_SYMBOL_GPL(mxs_pcm_platform_register); 81EXPORT_SYMBOL_GPL(mxs_pcm_platform_register);
228 82
229void mxs_pcm_platform_unregister(struct device *dev) 83void mxs_pcm_platform_unregister(struct device *dev)
230{ 84{
231 snd_soc_unregister_platform(dev); 85 snd_dmaengine_pcm_unregister(dev);
232} 86}
233EXPORT_SYMBOL_GPL(mxs_pcm_platform_unregister); 87EXPORT_SYMBOL_GPL(mxs_pcm_platform_unregister);
234 88
diff --git a/sound/soc/mxs/mxs-pcm.h b/sound/soc/mxs/mxs-pcm.h
index 35ba2ca42384..3aa918f9ed3e 100644
--- a/sound/soc/mxs/mxs-pcm.h
+++ b/sound/soc/mxs/mxs-pcm.h
@@ -19,8 +19,10 @@
19#ifndef _MXS_PCM_H 19#ifndef _MXS_PCM_H
20#define _MXS_PCM_H 20#define _MXS_PCM_H
21 21
22#include <linux/fsl/mxs-dma.h>
23
22struct mxs_pcm_dma_params { 24struct mxs_pcm_dma_params {
23 int chan_irq; 25 struct mxs_dma_data dma_data;
24 int chan_num; 26 int chan_num;
25}; 27};
26 28
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c
index 41a6136e3535..d31dc52fa862 100644
--- a/sound/soc/mxs/mxs-saif.c
+++ b/sound/soc/mxs/mxs-saif.c
@@ -370,7 +370,6 @@ static int mxs_saif_startup(struct snd_pcm_substream *substream,
370 struct snd_soc_dai *cpu_dai) 370 struct snd_soc_dai *cpu_dai)
371{ 371{
372 struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); 372 struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
373 snd_soc_dai_set_dma_data(cpu_dai, substream, &saif->dma_param);
374 373
375 /* clear error status to 0 for each re-open */ 374 /* clear error status to 0 for each re-open */
376 saif->fifo_underrun = 0; 375 saif->fifo_underrun = 0;
@@ -606,6 +605,8 @@ static int mxs_saif_dai_probe(struct snd_soc_dai *dai)
606 struct mxs_saif *saif = dev_get_drvdata(dai->dev); 605 struct mxs_saif *saif = dev_get_drvdata(dai->dev);
607 606
608 snd_soc_dai_set_drvdata(dai, saif); 607 snd_soc_dai_set_drvdata(dai, saif);
608 dai->playback_dma_data = &saif->dma_param;
609 dai->capture_dma_data = &saif->dma_param;
609 610
610 return 0; 611 return 0;
611} 612}
@@ -628,6 +629,10 @@ static struct snd_soc_dai_driver mxs_saif_dai = {
628 .ops = &mxs_saif_dai_ops, 629 .ops = &mxs_saif_dai_ops,
629}; 630};
630 631
632static const struct snd_soc_component_driver mxs_saif_component = {
633 .name = "mxs-saif",
634};
635
631static irqreturn_t mxs_saif_irq(int irq, void *dev_id) 636static irqreturn_t mxs_saif_irq(int irq, void *dev_id)
632{ 637{
633 struct mxs_saif *saif = dev_id; 638 struct mxs_saif *saif = dev_id;
@@ -754,9 +759,9 @@ static int mxs_saif_probe(struct platform_device *pdev)
754 return ret; 759 return ret;
755 } 760 }
756 761
757 saif->dma_param.chan_irq = platform_get_irq(pdev, 1); 762 saif->dma_param.dma_data.chan_irq = platform_get_irq(pdev, 1);
758 if (saif->dma_param.chan_irq < 0) { 763 if (saif->dma_param.dma_data.chan_irq < 0) {
759 ret = saif->dma_param.chan_irq; 764 ret = saif->dma_param.dma_data.chan_irq;
760 dev_err(&pdev->dev, "failed to get dma irq resource: %d\n", 765 dev_err(&pdev->dev, "failed to get dma irq resource: %d\n",
761 ret); 766 ret);
762 return ret; 767 return ret;
@@ -764,7 +769,8 @@ static int mxs_saif_probe(struct platform_device *pdev)
764 769
765 platform_set_drvdata(pdev, saif); 770 platform_set_drvdata(pdev, saif);
766 771
767 ret = snd_soc_register_dai(&pdev->dev, &mxs_saif_dai); 772 ret = snd_soc_register_component(&pdev->dev, &mxs_saif_component,
773 &mxs_saif_dai, 1);
768 if (ret) { 774 if (ret) {
769 dev_err(&pdev->dev, "register DAI failed\n"); 775 dev_err(&pdev->dev, "register DAI failed\n");
770 return ret; 776 return ret;
@@ -779,7 +785,7 @@ static int mxs_saif_probe(struct platform_device *pdev)
779 return 0; 785 return 0;
780 786
781failed_pdev_alloc: 787failed_pdev_alloc:
782 snd_soc_unregister_dai(&pdev->dev); 788 snd_soc_unregister_component(&pdev->dev);
783 789
784 return ret; 790 return ret;
785} 791}
@@ -787,7 +793,7 @@ failed_pdev_alloc:
787static int mxs_saif_remove(struct platform_device *pdev) 793static int mxs_saif_remove(struct platform_device *pdev)
788{ 794{
789 mxs_pcm_platform_unregister(&pdev->dev); 795 mxs_pcm_platform_unregister(&pdev->dev);
790 snd_soc_unregister_dai(&pdev->dev); 796 snd_soc_unregister_component(&pdev->dev);
791 797
792 return 0; 798 return 0;
793} 799}
diff --git a/sound/soc/nuc900/nuc900-ac97.c b/sound/soc/nuc900/nuc900-ac97.c
index 0418467a4848..fe3285ceaf5b 100644
--- a/sound/soc/nuc900/nuc900-ac97.c
+++ b/sound/soc/nuc900/nuc900-ac97.c
@@ -314,6 +314,10 @@ static struct snd_soc_dai_driver nuc900_ac97_dai = {
314 .ops = &nuc900_ac97_dai_ops, 314 .ops = &nuc900_ac97_dai_ops,
315}; 315};
316 316
317static const struct snd_soc_component_driver nuc900_ac97_component = {
318 .name = "nuc900-ac97",
319};
320
317static int nuc900_ac97_drvprobe(struct platform_device *pdev) 321static int nuc900_ac97_drvprobe(struct platform_device *pdev)
318{ 322{
319 struct nuc900_audio *nuc900_audio; 323 struct nuc900_audio *nuc900_audio;
@@ -361,7 +365,8 @@ static int nuc900_ac97_drvprobe(struct platform_device *pdev)
361 365
362 nuc900_ac97_data = nuc900_audio; 366 nuc900_ac97_data = nuc900_audio;
363 367
364 ret = snd_soc_register_dai(&pdev->dev, &nuc900_ac97_dai); 368 ret = snd_soc_register_component(&pdev->dev, &nuc900_ac97_component,
369 &nuc900_ac97_dai, 1);
365 if (ret) 370 if (ret)
366 goto out3; 371 goto out3;
367 372
@@ -384,7 +389,7 @@ out0:
384 389
385static int nuc900_ac97_drvremove(struct platform_device *pdev) 390static int nuc900_ac97_drvremove(struct platform_device *pdev)
386{ 391{
387 snd_soc_unregister_dai(&pdev->dev); 392 snd_soc_unregister_component(&pdev->dev);
388 393
389 clk_put(nuc900_ac97_data->clk); 394 clk_put(nuc900_ac97_data->clk);
390 iounmap(nuc900_ac97_data->mmio); 395 iounmap(nuc900_ac97_data->mmio);
diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c
index c1900b2a6f28..994dcf345975 100644
--- a/sound/soc/omap/am3517evm.c
+++ b/sound/soc/omap/am3517evm.c
@@ -28,7 +28,6 @@
28#include <linux/platform_data/asoc-ti-mcbsp.h> 28#include <linux/platform_data/asoc-ti-mcbsp.h>
29 29
30#include "omap-mcbsp.h" 30#include "omap-mcbsp.h"
31#include "omap-pcm.h"
32 31
33#include "../codecs/tlv320aic23.h" 32#include "../codecs/tlv320aic23.h"
34 33
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c
index 2600447fa74f..629446482a91 100644
--- a/sound/soc/omap/ams-delta.c
+++ b/sound/soc/omap/ams-delta.c
@@ -36,7 +36,6 @@
36#include <linux/platform_data/asoc-ti-mcbsp.h> 36#include <linux/platform_data/asoc-ti-mcbsp.h>
37 37
38#include "omap-mcbsp.h" 38#include "omap-mcbsp.h"
39#include "omap-pcm.h"
40#include "../codecs/cx20442.h" 39#include "../codecs/cx20442.h"
41 40
42 41
diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c
index 285c8368cb47..eb68c7db1cf3 100644
--- a/sound/soc/omap/mcbsp.c
+++ b/sound/soc/omap/mcbsp.c
@@ -1018,9 +1018,10 @@ int omap_mcbsp_init(struct platform_device *pdev)
1018 return -ENODEV; 1018 return -ENODEV;
1019 } 1019 }
1020 /* RX DMA request number, and port address configuration */ 1020 /* RX DMA request number, and port address configuration */
1021 mcbsp->dma_data[1].name = "Audio Capture"; 1021 mcbsp->dma_req[1] = res->start;
1022 mcbsp->dma_data[1].dma_req = res->start; 1022 mcbsp->dma_data[1].filter_data = &mcbsp->dma_req[1];
1023 mcbsp->dma_data[1].port_addr = omap_mcbsp_dma_reg_params(mcbsp, 1); 1023 mcbsp->dma_data[1].addr = omap_mcbsp_dma_reg_params(mcbsp, 1);
1024 mcbsp->dma_data[1].maxburst = 4;
1024 1025
1025 res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx"); 1026 res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
1026 if (!res) { 1027 if (!res) {
@@ -1028,9 +1029,10 @@ int omap_mcbsp_init(struct platform_device *pdev)
1028 return -ENODEV; 1029 return -ENODEV;
1029 } 1030 }
1030 /* TX DMA request number, and port address configuration */ 1031 /* TX DMA request number, and port address configuration */
1031 mcbsp->dma_data[0].name = "Audio Playback"; 1032 mcbsp->dma_req[0] = res->start;
1032 mcbsp->dma_data[0].dma_req = res->start; 1033 mcbsp->dma_data[0].filter_data = &mcbsp->dma_req[0];
1033 mcbsp->dma_data[0].port_addr = omap_mcbsp_dma_reg_params(mcbsp, 0); 1034 mcbsp->dma_data[0].addr = omap_mcbsp_dma_reg_params(mcbsp, 0);
1035 mcbsp->dma_data[0].maxburst = 4;
1034 1036
1035 mcbsp->fclk = clk_get(&pdev->dev, "fck"); 1037 mcbsp->fclk = clk_get(&pdev->dev, "fck");
1036 if (IS_ERR(mcbsp->fclk)) { 1038 if (IS_ERR(mcbsp->fclk)) {
diff --git a/sound/soc/omap/mcbsp.h b/sound/soc/omap/mcbsp.h
index f93e0b0af303..96d1b086bcf8 100644
--- a/sound/soc/omap/mcbsp.h
+++ b/sound/soc/omap/mcbsp.h
@@ -24,14 +24,14 @@
24#ifndef __ASOC_MCBSP_H 24#ifndef __ASOC_MCBSP_H
25#define __ASOC_MCBSP_H 25#define __ASOC_MCBSP_H
26 26
27#include "omap-pcm.h"
28
29#ifdef CONFIG_ARCH_OMAP1 27#ifdef CONFIG_ARCH_OMAP1
30#define mcbsp_omap1() 1 28#define mcbsp_omap1() 1
31#else 29#else
32#define mcbsp_omap1() 0 30#define mcbsp_omap1() 0
33#endif 31#endif
34 32
33#include <sound/dmaengine_pcm.h>
34
35/* McBSP register numbers. Register address offset = num * reg_step */ 35/* McBSP register numbers. Register address offset = num * reg_step */
36enum { 36enum {
37 /* Common registers */ 37 /* Common registers */
@@ -312,7 +312,8 @@ struct omap_mcbsp {
312 struct omap_mcbsp_platform_data *pdata; 312 struct omap_mcbsp_platform_data *pdata;
313 struct omap_mcbsp_st_data *st_data; 313 struct omap_mcbsp_st_data *st_data;
314 struct omap_mcbsp_reg_cfg cfg_regs; 314 struct omap_mcbsp_reg_cfg cfg_regs;
315 struct omap_pcm_dma_data dma_data[2]; 315 struct snd_dmaengine_dai_dma_data dma_data[2];
316 unsigned int dma_req[2];
316 int dma_op_mode; 317 int dma_op_mode;
317 u16 max_tx_thres; 318 u16 max_tx_thres;
318 u16 max_rx_thres; 319 u16 max_rx_thres;
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c
index ee7cd53aa3ee..5e8d640d314f 100644
--- a/sound/soc/omap/n810.c
+++ b/sound/soc/omap/n810.c
@@ -34,7 +34,6 @@
34#include <linux/platform_data/asoc-ti-mcbsp.h> 34#include <linux/platform_data/asoc-ti-mcbsp.h>
35 35
36#include "omap-mcbsp.h" 36#include "omap-mcbsp.h"
37#include "omap-pcm.h"
38 37
39#define N810_HEADSET_AMP_GPIO 10 38#define N810_HEADSET_AMP_GPIO 10
40#define N810_SPEAKER_AMP_GPIO 101 39#define N810_SPEAKER_AMP_GPIO 101
diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c
index e7d93fa412a9..70cd5c7b2e14 100644
--- a/sound/soc/omap/omap-abe-twl6040.c
+++ b/sound/soc/omap/omap-abe-twl6040.c
@@ -34,7 +34,6 @@
34 34
35#include "omap-dmic.h" 35#include "omap-dmic.h"
36#include "omap-mcpdm.h" 36#include "omap-mcpdm.h"
37#include "omap-pcm.h"
38#include "../codecs/twl6040.h" 37#include "../codecs/twl6040.h"
39 38
40struct abe_twl6040 { 39struct abe_twl6040 {
diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c
index ba49ccd9eed9..2ad0370146fd 100644
--- a/sound/soc/omap/omap-dmic.c
+++ b/sound/soc/omap/omap-dmic.c
@@ -39,8 +39,8 @@
39#include <sound/pcm_params.h> 39#include <sound/pcm_params.h>
40#include <sound/initval.h> 40#include <sound/initval.h>
41#include <sound/soc.h> 41#include <sound/soc.h>
42#include <sound/dmaengine_pcm.h>
42 43
43#include "omap-pcm.h"
44#include "omap-dmic.h" 44#include "omap-dmic.h"
45 45
46struct omap_dmic { 46struct omap_dmic {
@@ -55,13 +55,9 @@ struct omap_dmic {
55 u32 ch_enabled; 55 u32 ch_enabled;
56 bool active; 56 bool active;
57 struct mutex mutex; 57 struct mutex mutex;
58};
59 58
60/* 59 struct snd_dmaengine_dai_dma_data dma_data;
61 * Stream DMA parameters 60 unsigned int dma_req;
62 */
63static struct omap_pcm_dma_data omap_dmic_dai_dma_params = {
64 .name = "DMIC capture",
65}; 61};
66 62
67static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val) 63static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val)
@@ -118,7 +114,7 @@ static int omap_dmic_dai_startup(struct snd_pcm_substream *substream,
118 114
119 mutex_unlock(&dmic->mutex); 115 mutex_unlock(&dmic->mutex);
120 116
121 snd_soc_dai_set_dma_data(dai, substream, &omap_dmic_dai_dma_params); 117 snd_soc_dai_set_dma_data(dai, substream, &dmic->dma_data);
122 return ret; 118 return ret;
123} 119}
124 120
@@ -203,7 +199,7 @@ static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream,
203 struct snd_soc_dai *dai) 199 struct snd_soc_dai *dai)
204{ 200{
205 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); 201 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
206 struct omap_pcm_dma_data *dma_data; 202 struct snd_dmaengine_dai_dma_data *dma_data;
207 int channels; 203 int channels;
208 204
209 dmic->clk_div = omap_dmic_select_divider(dmic, params_rate(params)); 205 dmic->clk_div = omap_dmic_select_divider(dmic, params_rate(params));
@@ -230,7 +226,7 @@ static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream,
230 226
231 /* packet size is threshold * channels */ 227 /* packet size is threshold * channels */
232 dma_data = snd_soc_dai_get_dma_data(dai, substream); 228 dma_data = snd_soc_dai_get_dma_data(dai, substream);
233 dma_data->packet_size = dmic->threshold * channels; 229 dma_data->maxburst = dmic->threshold * channels;
234 230
235 return 0; 231 return 0;
236} 232}
@@ -448,6 +444,10 @@ static struct snd_soc_dai_driver omap_dmic_dai = {
448 .ops = &omap_dmic_dai_ops, 444 .ops = &omap_dmic_dai_ops,
449}; 445};
450 446
447static const struct snd_soc_component_driver omap_dmic_component = {
448 .name = "omap-dmic",
449};
450
451static int asoc_dmic_probe(struct platform_device *pdev) 451static int asoc_dmic_probe(struct platform_device *pdev)
452{ 452{
453 struct omap_dmic *dmic; 453 struct omap_dmic *dmic;
@@ -476,7 +476,7 @@ static int asoc_dmic_probe(struct platform_device *pdev)
476 ret = -ENODEV; 476 ret = -ENODEV;
477 goto err_put_clk; 477 goto err_put_clk;
478 } 478 }
479 omap_dmic_dai_dma_params.port_addr = res->start + OMAP_DMIC_DATA_REG; 479 dmic->dma_data.addr = res->start + OMAP_DMIC_DATA_REG;
480 480
481 res = platform_get_resource(pdev, IORESOURCE_DMA, 0); 481 res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
482 if (!res) { 482 if (!res) {
@@ -484,7 +484,9 @@ static int asoc_dmic_probe(struct platform_device *pdev)
484 ret = -ENODEV; 484 ret = -ENODEV;
485 goto err_put_clk; 485 goto err_put_clk;
486 } 486 }
487 omap_dmic_dai_dma_params.dma_req = res->start; 487
488 dmic->dma_req = res->start;
489 dmic->dma_data.filter_data = &dmic->dma_req;
488 490
489 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); 491 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
490 if (!res) { 492 if (!res) {
@@ -493,21 +495,12 @@ static int asoc_dmic_probe(struct platform_device *pdev)
493 goto err_put_clk; 495 goto err_put_clk;
494 } 496 }
495 497
496 if (!devm_request_mem_region(&pdev->dev, res->start, 498 dmic->io_base = devm_ioremap_resource(&pdev->dev, res);
497 resource_size(res), pdev->name)) { 499 if (IS_ERR(dmic->io_base))
498 dev_err(dmic->dev, "memory region already claimed\n"); 500 return PTR_ERR(dmic->io_base);
499 ret = -ENODEV;
500 goto err_put_clk;
501 }
502
503 dmic->io_base = devm_ioremap(&pdev->dev, res->start,
504 resource_size(res));
505 if (!dmic->io_base) {
506 ret = -ENOMEM;
507 goto err_put_clk;
508 }
509 501
510 ret = snd_soc_register_dai(&pdev->dev, &omap_dmic_dai); 502 ret = snd_soc_register_component(&pdev->dev, &omap_dmic_component,
503 &omap_dmic_dai, 1);
511 if (ret) 504 if (ret)
512 goto err_put_clk; 505 goto err_put_clk;
513 506
@@ -522,7 +515,7 @@ static int asoc_dmic_remove(struct platform_device *pdev)
522{ 515{
523 struct omap_dmic *dmic = platform_get_drvdata(pdev); 516 struct omap_dmic *dmic = platform_get_drvdata(pdev);
524 517
525 snd_soc_unregister_dai(&pdev->dev); 518 snd_soc_unregister_component(&pdev->dev);
526 clk_put(dmic->fclk); 519 clk_put(dmic->fclk);
527 520
528 return 0; 521 return 0;
diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c
index 32fa840c493e..ced3b88b44d4 100644
--- a/sound/soc/omap/omap-hdmi.c
+++ b/sound/soc/omap/omap-hdmi.c
@@ -32,15 +32,16 @@
32#include <sound/soc.h> 32#include <sound/soc.h>
33#include <sound/asound.h> 33#include <sound/asound.h>
34#include <sound/asoundef.h> 34#include <sound/asoundef.h>
35#include <sound/dmaengine_pcm.h>
35#include <video/omapdss.h> 36#include <video/omapdss.h>
36 37
37#include "omap-pcm.h"
38#include "omap-hdmi.h" 38#include "omap-hdmi.h"
39 39
40#define DRV_NAME "omap-hdmi-audio-dai" 40#define DRV_NAME "omap-hdmi-audio-dai"
41 41
42struct hdmi_priv { 42struct hdmi_priv {
43 struct omap_pcm_dma_data dma_params; 43 struct snd_dmaengine_dai_dma_data dma_data;
44 unsigned int dma_req;
44 struct omap_dss_audio dss_audio; 45 struct omap_dss_audio dss_audio;
45 struct snd_aes_iec958 iec; 46 struct snd_aes_iec958 iec;
46 struct snd_cea_861_aud_if cea; 47 struct snd_cea_861_aud_if cea;
@@ -68,7 +69,7 @@ static int omap_hdmi_dai_startup(struct snd_pcm_substream *substream,
68 return -ENODEV; 69 return -ENODEV;
69 } 70 }
70 71
71 snd_soc_dai_set_dma_data(dai, substream, &priv->dma_params); 72 snd_soc_dai_set_dma_data(dai, substream, &priv->dma_data);
72 73
73 return 0; 74 return 0;
74} 75}
@@ -88,25 +89,20 @@ static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
88 struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai); 89 struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai);
89 struct snd_aes_iec958 *iec = &priv->iec; 90 struct snd_aes_iec958 *iec = &priv->iec;
90 struct snd_cea_861_aud_if *cea = &priv->cea; 91 struct snd_cea_861_aud_if *cea = &priv->cea;
91 struct omap_pcm_dma_data *dma_data;
92 int err = 0; 92 int err = 0;
93 93
94 dma_data = snd_soc_dai_get_dma_data(dai, substream);
95
96 switch (params_format(params)) { 94 switch (params_format(params)) {
97 case SNDRV_PCM_FORMAT_S16_LE: 95 case SNDRV_PCM_FORMAT_S16_LE:
98 dma_data->packet_size = 16; 96 priv->dma_data.maxburst = 16;
99 break; 97 break;
100 case SNDRV_PCM_FORMAT_S24_LE: 98 case SNDRV_PCM_FORMAT_S24_LE:
101 dma_data->packet_size = 32; 99 priv->dma_data.maxburst = 32;
102 break; 100 break;
103 default: 101 default:
104 dev_err(dai->dev, "format not supported!\n"); 102 dev_err(dai->dev, "format not supported!\n");
105 return -EINVAL; 103 return -EINVAL;
106 } 104 }
107 105
108 dma_data->data_type = 32;
109
110 /* 106 /*
111 * fill the IEC-60958 channel status word 107 * fill the IEC-60958 channel status word
112 */ 108 */
@@ -264,6 +260,10 @@ static struct snd_soc_dai_driver omap_hdmi_dai = {
264 .ops = &omap_hdmi_dai_ops, 260 .ops = &omap_hdmi_dai_ops,
265}; 261};
266 262
263static const struct snd_soc_component_driver omap_hdmi_component = {
264 .name = DRV_NAME,
265};
266
267static int omap_hdmi_probe(struct platform_device *pdev) 267static int omap_hdmi_probe(struct platform_device *pdev)
268{ 268{
269 int ret; 269 int ret;
@@ -283,8 +283,7 @@ static int omap_hdmi_probe(struct platform_device *pdev)
283 return -ENODEV; 283 return -ENODEV;
284 } 284 }
285 285
286 hdmi_data->dma_params.port_addr = hdmi_rsrc->start 286 hdmi_data->dma_data.addr = hdmi_rsrc->start + OMAP_HDMI_AUDIO_DMA_PORT;
287 + OMAP_HDMI_AUDIO_DMA_PORT;
288 287
289 hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_DMA, 0); 288 hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_DMA, 0);
290 if (!hdmi_rsrc) { 289 if (!hdmi_rsrc) {
@@ -292,8 +291,9 @@ static int omap_hdmi_probe(struct platform_device *pdev)
292 return -ENODEV; 291 return -ENODEV;
293 } 292 }
294 293
295 hdmi_data->dma_params.dma_req = hdmi_rsrc->start; 294 hdmi_data->dma_req = hdmi_rsrc->start;
296 hdmi_data->dma_params.name = "HDMI playback"; 295 hdmi_data->dma_data.filter_data = &hdmi_data->dma_req;
296 hdmi_data->dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
297 297
298 /* 298 /*
299 * TODO: We assume that there is only one DSS HDMI device. Future 299 * TODO: We assume that there is only one DSS HDMI device. Future
@@ -321,7 +321,8 @@ static int omap_hdmi_probe(struct platform_device *pdev)
321 } 321 }
322 322
323 dev_set_drvdata(&pdev->dev, hdmi_data); 323 dev_set_drvdata(&pdev->dev, hdmi_data);
324 ret = snd_soc_register_dai(&pdev->dev, &omap_hdmi_dai); 324 ret = snd_soc_register_component(&pdev->dev, &omap_hdmi_component,
325 &omap_hdmi_dai, 1);
325 326
326 return ret; 327 return ret;
327} 328}
@@ -330,7 +331,7 @@ static int omap_hdmi_remove(struct platform_device *pdev)
330{ 331{
331 struct hdmi_priv *hdmi_data = dev_get_drvdata(&pdev->dev); 332 struct hdmi_priv *hdmi_data = dev_get_drvdata(&pdev->dev);
332 333
333 snd_soc_unregister_dai(&pdev->dev); 334 snd_soc_unregister_component(&pdev->dev);
334 335
335 if (hdmi_data == NULL) { 336 if (hdmi_data == NULL) {
336 dev_err(&pdev->dev, "cannot obtain HDMi data\n"); 337 dev_err(&pdev->dev, "cannot obtain HDMi data\n");
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 8d2defd6fdbe..eadbfb6b5000 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -33,11 +33,11 @@
33#include <sound/pcm_params.h> 33#include <sound/pcm_params.h>
34#include <sound/initval.h> 34#include <sound/initval.h>
35#include <sound/soc.h> 35#include <sound/soc.h>
36#include <sound/dmaengine_pcm.h>
36 37
37#include <linux/platform_data/asoc-ti-mcbsp.h> 38#include <linux/platform_data/asoc-ti-mcbsp.h>
38#include "mcbsp.h" 39#include "mcbsp.h"
39#include "omap-mcbsp.h" 40#include "omap-mcbsp.h"
40#include "omap-pcm.h"
41 41
42#define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_8000_96000) 42#define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_8000_96000)
43 43
@@ -62,24 +62,22 @@ enum {
62 * Stream DMA parameters. DMA request line and port address are set runtime 62 * Stream DMA parameters. DMA request line and port address are set runtime
63 * since they are different between OMAP1 and later OMAPs 63 * since they are different between OMAP1 and later OMAPs
64 */ 64 */
65static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream) 65static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream,
66 unsigned int packet_size)
66{ 67{
67 struct snd_soc_pcm_runtime *rtd = substream->private_data; 68 struct snd_soc_pcm_runtime *rtd = substream->private_data;
68 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 69 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
69 struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); 70 struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
70 struct omap_pcm_dma_data *dma_data;
71 int words; 71 int words;
72 72
73 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
74
75 /* 73 /*
76 * Configure McBSP threshold based on either: 74 * Configure McBSP threshold based on either:
77 * packet_size, when the sDMA is in packet mode, or based on the 75 * packet_size, when the sDMA is in packet mode, or based on the
78 * period size in THRESHOLD mode, otherwise use McBSP threshold = 1 76 * period size in THRESHOLD mode, otherwise use McBSP threshold = 1
79 * for mono streams. 77 * for mono streams.
80 */ 78 */
81 if (dma_data->packet_size) 79 if (packet_size)
82 words = dma_data->packet_size; 80 words = packet_size;
83 else 81 else
84 words = 1; 82 words = 1;
85 83
@@ -226,7 +224,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
226{ 224{
227 struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); 225 struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
228 struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs; 226 struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs;
229 struct omap_pcm_dma_data *dma_data; 227 struct snd_dmaengine_dai_dma_data *dma_data;
230 int wlen, channels, wpf; 228 int wlen, channels, wpf;
231 int pkt_size = 0; 229 int pkt_size = 0;
232 unsigned int format, div, framesize, master; 230 unsigned int format, div, framesize, master;
@@ -245,7 +243,6 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
245 return -EINVAL; 243 return -EINVAL;
246 } 244 }
247 if (mcbsp->pdata->buffer_size) { 245 if (mcbsp->pdata->buffer_size) {
248 dma_data->set_threshold = omap_mcbsp_set_threshold;
249 if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) { 246 if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) {
250 int period_words, max_thrsh; 247 int period_words, max_thrsh;
251 int divider = 0; 248 int divider = 0;
@@ -276,9 +273,10 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
276 /* Use packet mode for non mono streams */ 273 /* Use packet mode for non mono streams */
277 pkt_size = channels; 274 pkt_size = channels;
278 } 275 }
276 omap_mcbsp_set_threshold(substream, pkt_size);
279 } 277 }
280 278
281 dma_data->packet_size = pkt_size; 279 dma_data->maxburst = pkt_size;
282 280
283 if (mcbsp->configured) { 281 if (mcbsp->configured) {
284 /* McBSP already configured by another stream */ 282 /* McBSP already configured by another stream */
@@ -586,6 +584,10 @@ static struct snd_soc_dai_driver omap_mcbsp_dai = {
586 .ops = &mcbsp_dai_ops, 584 .ops = &mcbsp_dai_ops,
587}; 585};
588 586
587static const struct snd_soc_component_driver omap_mcbsp_component = {
588 .name = "omap-mcbsp",
589};
590
589static int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol, 591static int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol,
590 struct snd_ctl_elem_info *uinfo) 592 struct snd_ctl_elem_info *uinfo)
591{ 593{
@@ -793,7 +795,8 @@ static int asoc_mcbsp_probe(struct platform_device *pdev)
793 795
794 ret = omap_mcbsp_init(pdev); 796 ret = omap_mcbsp_init(pdev);
795 if (!ret) 797 if (!ret)
796 return snd_soc_register_dai(&pdev->dev, &omap_mcbsp_dai); 798 return snd_soc_register_component(&pdev->dev, &omap_mcbsp_component,
799 &omap_mcbsp_dai, 1);
797 800
798 return ret; 801 return ret;
799} 802}
@@ -802,7 +805,7 @@ static int asoc_mcbsp_remove(struct platform_device *pdev)
802{ 805{
803 struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev); 806 struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
804 807
805 snd_soc_unregister_dai(&pdev->dev); 808 snd_soc_unregister_component(&pdev->dev);
806 809
807 if (mcbsp->pdata->ops && mcbsp->pdata->ops->free) 810 if (mcbsp->pdata->ops && mcbsp->pdata->ops->free)
808 mcbsp->pdata->ops->free(mcbsp->id); 811 mcbsp->pdata->ops->free(mcbsp->id);
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
index 5ca11bdac21e..eb05c7ed6d05 100644
--- a/sound/soc/omap/omap-mcpdm.c
+++ b/sound/soc/omap/omap-mcpdm.c
@@ -39,11 +39,14 @@
39#include <sound/pcm.h> 39#include <sound/pcm.h>
40#include <sound/pcm_params.h> 40#include <sound/pcm_params.h>
41#include <sound/soc.h> 41#include <sound/soc.h>
42#include <sound/dmaengine_pcm.h>
42 43
43#include "omap-mcpdm.h" 44#include "omap-mcpdm.h"
44#include "omap-pcm.h"
45 45
46#define OMAP44XX_MCPDM_L3_BASE 0x49032000 46struct mcpdm_link_config {
47 u32 link_mask; /* channel mask for the direction */
48 u32 threshold; /* FIFO threshold */
49};
47 50
48struct omap_mcpdm { 51struct omap_mcpdm {
49 struct device *dev; 52 struct device *dev;
@@ -53,29 +56,22 @@ struct omap_mcpdm {
53 56
54 struct mutex mutex; 57 struct mutex mutex;
55 58
56 /* channel data */ 59 /* Playback/Capture configuration */
57 u32 dn_channels; 60 struct mcpdm_link_config config[2];
58 u32 up_channels;
59
60 /* McPDM FIFO thresholds */
61 u32 dn_threshold;
62 u32 up_threshold;
63 61
64 /* McPDM dn offsets for rx1, and 2 channels */ 62 /* McPDM dn offsets for rx1, and 2 channels */
65 u32 dn_rx_offset; 63 u32 dn_rx_offset;
64
65 /* McPDM needs to be restarted due to runtime reconfiguration */
66 bool restart;
67
68 struct snd_dmaengine_dai_dma_data dma_data[2];
69 unsigned int dma_req[2];
66}; 70};
67 71
68/* 72/*
69 * Stream DMA parameters 73 * Stream DMA parameters
70 */ 74 */
71static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = {
72 {
73 .name = "Audio playback",
74 },
75 {
76 .name = "Audio capture",
77 },
78};
79 75
80static inline void omap_mcpdm_write(struct omap_mcpdm *mcpdm, u16 reg, u32 val) 76static inline void omap_mcpdm_write(struct omap_mcpdm *mcpdm, u16 reg, u32 val)
81{ 77{
@@ -130,11 +126,12 @@ static void omap_mcpdm_reg_dump(struct omap_mcpdm *mcpdm) {}
130static void omap_mcpdm_start(struct omap_mcpdm *mcpdm) 126static void omap_mcpdm_start(struct omap_mcpdm *mcpdm)
131{ 127{
132 u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL); 128 u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
129 u32 link_mask = mcpdm->config[0].link_mask | mcpdm->config[1].link_mask;
133 130
134 ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); 131 ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
135 omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); 132 omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
136 133
137 ctrl |= mcpdm->dn_channels | mcpdm->up_channels; 134 ctrl |= link_mask;
138 omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); 135 omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
139 136
140 ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); 137 ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
@@ -148,11 +145,12 @@ static void omap_mcpdm_start(struct omap_mcpdm *mcpdm)
148static void omap_mcpdm_stop(struct omap_mcpdm *mcpdm) 145static void omap_mcpdm_stop(struct omap_mcpdm *mcpdm)
149{ 146{
150 u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL); 147 u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
148 u32 link_mask = MCPDM_PDM_DN_MASK | MCPDM_PDM_UP_MASK;
151 149
152 ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); 150 ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
153 omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); 151 omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
154 152
155 ctrl &= ~(mcpdm->dn_channels | mcpdm->up_channels); 153 ctrl &= ~(link_mask);
156 omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); 154 omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
157 155
158 ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); 156 ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
@@ -188,8 +186,10 @@ static void omap_mcpdm_open_streams(struct omap_mcpdm *mcpdm)
188 omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, dn_offset); 186 omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, dn_offset);
189 } 187 }
190 188
191 omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_DN, mcpdm->dn_threshold); 189 omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_DN,
192 omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_UP, mcpdm->up_threshold); 190 mcpdm->config[SNDRV_PCM_STREAM_PLAYBACK].threshold);
191 omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_UP,
192 mcpdm->config[SNDRV_PCM_STREAM_CAPTURE].threshold);
193 193
194 omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_SET, 194 omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_SET,
195 MCPDM_DMA_DN_ENABLE | MCPDM_DMA_UP_ENABLE); 195 MCPDM_DMA_DN_ENABLE | MCPDM_DMA_UP_ENABLE);
@@ -267,7 +267,7 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,
267 mutex_unlock(&mcpdm->mutex); 267 mutex_unlock(&mcpdm->mutex);
268 268
269 snd_soc_dai_set_dma_data(dai, substream, 269 snd_soc_dai_set_dma_data(dai, substream,
270 &omap_mcpdm_dai_dma_params[substream->stream]); 270 &mcpdm->dma_data[substream->stream]);
271 271
272 return 0; 272 return 0;
273} 273}
@@ -283,6 +283,8 @@ static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
283 if (omap_mcpdm_active(mcpdm)) { 283 if (omap_mcpdm_active(mcpdm)) {
284 omap_mcpdm_stop(mcpdm); 284 omap_mcpdm_stop(mcpdm);
285 omap_mcpdm_close_streams(mcpdm); 285 omap_mcpdm_close_streams(mcpdm);
286 mcpdm->config[0].link_mask = 0;
287 mcpdm->config[1].link_mask = 0;
286 } 288 }
287 } 289 }
288 290
@@ -295,7 +297,8 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
295{ 297{
296 struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); 298 struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
297 int stream = substream->stream; 299 int stream = substream->stream;
298 struct omap_pcm_dma_data *dma_data; 300 struct snd_dmaengine_dai_dma_data *dma_data;
301 u32 threshold;
299 int channels; 302 int channels;
300 int link_mask = 0; 303 int link_mask = 0;
301 304
@@ -325,16 +328,32 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
325 328
326 dma_data = snd_soc_dai_get_dma_data(dai, substream); 329 dma_data = snd_soc_dai_get_dma_data(dai, substream);
327 330
331 threshold = mcpdm->config[stream].threshold;
328 /* Configure McPDM channels, and DMA packet size */ 332 /* Configure McPDM channels, and DMA packet size */
329 if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 333 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
330 mcpdm->dn_channels = link_mask << 3; 334 link_mask <<= 3;
331 dma_data->packet_size = 335
332 (MCPDM_DN_THRES_MAX - mcpdm->dn_threshold) * channels; 336 /* If capture is not running assume a stereo stream to come */
337 if (!mcpdm->config[!stream].link_mask)
338 mcpdm->config[!stream].link_mask = 0x3;
339
340 dma_data->maxburst =
341 (MCPDM_DN_THRES_MAX - threshold) * channels;
333 } else { 342 } else {
334 mcpdm->up_channels = link_mask << 0; 343 /* If playback is not running assume a stereo stream to come */
335 dma_data->packet_size = mcpdm->up_threshold * channels; 344 if (!mcpdm->config[!stream].link_mask)
345 mcpdm->config[!stream].link_mask = (0x3 << 3);
346
347 dma_data->maxburst = threshold * channels;
336 } 348 }
337 349
350 /* Check if we need to restart McPDM with this stream */
351 if (mcpdm->config[stream].link_mask &&
352 mcpdm->config[stream].link_mask != link_mask)
353 mcpdm->restart = true;
354
355 mcpdm->config[stream].link_mask = link_mask;
356
338 return 0; 357 return 0;
339} 358}
340 359
@@ -346,6 +365,11 @@ static int omap_mcpdm_prepare(struct snd_pcm_substream *substream,
346 if (!omap_mcpdm_active(mcpdm)) { 365 if (!omap_mcpdm_active(mcpdm)) {
347 omap_mcpdm_start(mcpdm); 366 omap_mcpdm_start(mcpdm);
348 omap_mcpdm_reg_dump(mcpdm); 367 omap_mcpdm_reg_dump(mcpdm);
368 } else if (mcpdm->restart) {
369 omap_mcpdm_stop(mcpdm);
370 omap_mcpdm_start(mcpdm);
371 mcpdm->restart = false;
372 omap_mcpdm_reg_dump(mcpdm);
349 } 373 }
350 374
351 return 0; 375 return 0;
@@ -369,7 +393,7 @@ static int omap_mcpdm_probe(struct snd_soc_dai *dai)
369 pm_runtime_get_sync(mcpdm->dev); 393 pm_runtime_get_sync(mcpdm->dev);
370 omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, 0x00); 394 omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, 0x00);
371 395
372 ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler, 396 ret = devm_request_irq(mcpdm->dev, mcpdm->irq, omap_mcpdm_irq_handler,
373 0, "McPDM", (void *)mcpdm); 397 0, "McPDM", (void *)mcpdm);
374 398
375 pm_runtime_put_sync(mcpdm->dev); 399 pm_runtime_put_sync(mcpdm->dev);
@@ -380,8 +404,9 @@ static int omap_mcpdm_probe(struct snd_soc_dai *dai)
380 } 404 }
381 405
382 /* Configure McPDM threshold values */ 406 /* Configure McPDM threshold values */
383 mcpdm->dn_threshold = 2; 407 mcpdm->config[SNDRV_PCM_STREAM_PLAYBACK].threshold = 2;
384 mcpdm->up_threshold = MCPDM_UP_THRES_MAX - 3; 408 mcpdm->config[SNDRV_PCM_STREAM_CAPTURE].threshold =
409 MCPDM_UP_THRES_MAX - 3;
385 return ret; 410 return ret;
386} 411}
387 412
@@ -389,7 +414,6 @@ static int omap_mcpdm_remove(struct snd_soc_dai *dai)
389{ 414{
390 struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); 415 struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
391 416
392 free_irq(mcpdm->irq, (void *)mcpdm);
393 pm_runtime_disable(mcpdm->dev); 417 pm_runtime_disable(mcpdm->dev);
394 418
395 return 0; 419 return 0;
@@ -420,6 +444,10 @@ static struct snd_soc_dai_driver omap_mcpdm_dai = {
420 .ops = &omap_mcpdm_dai_ops, 444 .ops = &omap_mcpdm_dai_ops,
421}; 445};
422 446
447static const struct snd_soc_component_driver omap_mcpdm_component = {
448 .name = "omap-mcpdm",
449};
450
423void omap_mcpdm_configure_dn_offsets(struct snd_soc_pcm_runtime *rtd, 451void omap_mcpdm_configure_dn_offsets(struct snd_soc_pcm_runtime *rtd,
424 u8 rx1, u8 rx2) 452 u8 rx1, u8 rx2)
425{ 453{
@@ -446,33 +474,30 @@ static int asoc_mcpdm_probe(struct platform_device *pdev)
446 if (res == NULL) 474 if (res == NULL)
447 return -ENOMEM; 475 return -ENOMEM;
448 476
449 omap_mcpdm_dai_dma_params[0].port_addr = res->start + MCPDM_REG_DN_DATA; 477 mcpdm->dma_data[0].addr = res->start + MCPDM_REG_DN_DATA;
450 omap_mcpdm_dai_dma_params[1].port_addr = res->start + MCPDM_REG_UP_DATA; 478 mcpdm->dma_data[1].addr = res->start + MCPDM_REG_UP_DATA;
451 479
452 res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "dn_link"); 480 res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "dn_link");
453 if (!res) 481 if (!res)
454 return -ENODEV; 482 return -ENODEV;
455 483
456 omap_mcpdm_dai_dma_params[0].dma_req = res->start; 484 mcpdm->dma_req[0] = res->start;
485 mcpdm->dma_data[0].filter_data = &mcpdm->dma_req[0];
457 486
458 res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "up_link"); 487 res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "up_link");
459 if (!res) 488 if (!res)
460 return -ENODEV; 489 return -ENODEV;
461 490
462 omap_mcpdm_dai_dma_params[1].dma_req = res->start; 491 mcpdm->dma_req[1] = res->start;
492 mcpdm->dma_data[1].filter_data = &mcpdm->dma_req[1];
463 493
464 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); 494 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
465 if (res == NULL) 495 if (res == NULL)
466 return -ENOMEM; 496 return -ENOMEM;
467 497
468 if (!devm_request_mem_region(&pdev->dev, res->start, 498 mcpdm->io_base = devm_ioremap_resource(&pdev->dev, res);
469 resource_size(res), "McPDM")) 499 if (IS_ERR(mcpdm->io_base))
470 return -EBUSY; 500 return PTR_ERR(mcpdm->io_base);
471
472 mcpdm->io_base = devm_ioremap(&pdev->dev, res->start,
473 resource_size(res));
474 if (!mcpdm->io_base)
475 return -ENOMEM;
476 501
477 mcpdm->irq = platform_get_irq(pdev, 0); 502 mcpdm->irq = platform_get_irq(pdev, 0);
478 if (mcpdm->irq < 0) 503 if (mcpdm->irq < 0)
@@ -480,12 +505,13 @@ static int asoc_mcpdm_probe(struct platform_device *pdev)
480 505
481 mcpdm->dev = &pdev->dev; 506 mcpdm->dev = &pdev->dev;
482 507
483 return snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai); 508 return snd_soc_register_component(&pdev->dev, &omap_mcpdm_component,
509 &omap_mcpdm_dai, 1);
484} 510}
485 511
486static int asoc_mcpdm_remove(struct platform_device *pdev) 512static int asoc_mcpdm_remove(struct platform_device *pdev)
487{ 513{
488 snd_soc_unregister_dai(&pdev->dev); 514 snd_soc_unregister_component(&pdev->dev);
489 return 0; 515 return 0;
490} 516}
491 517
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index c722c2ef9665..c28e042f2208 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -32,8 +32,6 @@
32#include <sound/dmaengine_pcm.h> 32#include <sound/dmaengine_pcm.h>
33#include <sound/soc.h> 33#include <sound/soc.h>
34 34
35#include "omap-pcm.h"
36
37#ifdef CONFIG_ARCH_OMAP1 35#ifdef CONFIG_ARCH_OMAP1
38#define pcm_omap1510() cpu_is_omap1510() 36#define pcm_omap1510() cpu_is_omap1510()
39#else 37#else
@@ -56,25 +54,6 @@ static const struct snd_pcm_hardware omap_pcm_hardware = {
56 .buffer_bytes_max = 128 * 1024, 54 .buffer_bytes_max = 128 * 1024,
57}; 55};
58 56
59static int omap_pcm_get_dma_buswidth(int num_bits)
60{
61 int buswidth;
62
63 switch (num_bits) {
64 case 16:
65 buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
66 break;
67 case 32:
68 buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
69 break;
70 default:
71 buswidth = -EINVAL;
72 break;
73 }
74 return buswidth;
75}
76
77
78/* this may get called several times by oss emulation */ 57/* this may get called several times by oss emulation */
79static int omap_pcm_hw_params(struct snd_pcm_substream *substream, 58static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
80 struct snd_pcm_hw_params *params) 59 struct snd_pcm_hw_params *params)
@@ -105,20 +84,9 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
105 if (err) 84 if (err)
106 return err; 85 return err;
107 86
108 /* Override the *_dma addr_width if requested by the DAI driver */ 87 snd_dmaengine_pcm_set_config_from_dai_data(substream,
109 if (dma_data->data_type) { 88 snd_soc_dai_get_dma_data(rtd->cpu_dai, substream),
110 int buswidth = omap_pcm_get_dma_buswidth(dma_data->data_type); 89 &config);
111
112 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
113 config.dst_addr_width = buswidth;
114 else
115 config.src_addr_width = buswidth;
116 }
117
118 config.src_addr = dma_data->port_addr;
119 config.dst_addr = dma_data->port_addr;
120 config.src_maxburst = dma_data->packet_size;
121 config.dst_maxburst = dma_data->packet_size;
122 90
123 return dmaengine_slave_config(chan, &config); 91 return dmaengine_slave_config(chan, &config);
124} 92}
@@ -129,37 +97,6 @@ static int omap_pcm_hw_free(struct snd_pcm_substream *substream)
129 return 0; 97 return 0;
130} 98}
131 99
132static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
133{
134 struct snd_soc_pcm_runtime *rtd = substream->private_data;
135 struct omap_pcm_dma_data *dma_data;
136 int ret = 0;
137
138 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
139
140 switch (cmd) {
141 case SNDRV_PCM_TRIGGER_START:
142 case SNDRV_PCM_TRIGGER_RESUME:
143 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
144 /* Configure McBSP internal buffer usage */
145 if (dma_data->set_threshold)
146 dma_data->set_threshold(substream);
147 break;
148
149 case SNDRV_PCM_TRIGGER_STOP:
150 case SNDRV_PCM_TRIGGER_SUSPEND:
151 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
152 break;
153 default:
154 ret = -EINVAL;
155 }
156
157 if (ret == 0)
158 ret = snd_dmaengine_pcm_trigger(substream, cmd);
159
160 return ret;
161}
162
163static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream) 100static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream)
164{ 101{
165 snd_pcm_uframes_t offset; 102 snd_pcm_uframes_t offset;
@@ -175,20 +112,15 @@ static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream)
175static int omap_pcm_open(struct snd_pcm_substream *substream) 112static int omap_pcm_open(struct snd_pcm_substream *substream)
176{ 113{
177 struct snd_soc_pcm_runtime *rtd = substream->private_data; 114 struct snd_soc_pcm_runtime *rtd = substream->private_data;
178 struct omap_pcm_dma_data *dma_data; 115 struct snd_dmaengine_dai_dma_data *dma_data;
179 116
180 snd_soc_set_runtime_hwparams(substream, &omap_pcm_hardware); 117 snd_soc_set_runtime_hwparams(substream, &omap_pcm_hardware);
181 118
182 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); 119 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
183 120
184 return snd_dmaengine_pcm_open(substream, omap_dma_filter_fn, 121 return snd_dmaengine_pcm_open_request_chan(substream,
185 &dma_data->dma_req); 122 omap_dma_filter_fn,
186} 123 dma_data->filter_data);
187
188static int omap_pcm_close(struct snd_pcm_substream *substream)
189{
190 snd_dmaengine_pcm_close(substream);
191 return 0;
192} 124}
193 125
194static int omap_pcm_mmap(struct snd_pcm_substream *substream, 126static int omap_pcm_mmap(struct snd_pcm_substream *substream,
@@ -204,11 +136,11 @@ static int omap_pcm_mmap(struct snd_pcm_substream *substream,
204 136
205static struct snd_pcm_ops omap_pcm_ops = { 137static struct snd_pcm_ops omap_pcm_ops = {
206 .open = omap_pcm_open, 138 .open = omap_pcm_open,
207 .close = omap_pcm_close, 139 .close = snd_dmaengine_pcm_close_release_chan,
208 .ioctl = snd_pcm_lib_ioctl, 140 .ioctl = snd_pcm_lib_ioctl,
209 .hw_params = omap_pcm_hw_params, 141 .hw_params = omap_pcm_hw_params,
210 .hw_free = omap_pcm_hw_free, 142 .hw_free = omap_pcm_hw_free,
211 .trigger = omap_pcm_trigger, 143 .trigger = snd_dmaengine_pcm_trigger,
212 .pointer = omap_pcm_pointer, 144 .pointer = omap_pcm_pointer,
213 .mmap = omap_pcm_mmap, 145 .mmap = omap_pcm_mmap,
214}; 146};
diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h
deleted file mode 100644
index cabe74c4068b..000000000000
--- a/sound/soc/omap/omap-pcm.h
+++ /dev/null
@@ -1,40 +0,0 @@
1/*
2 * omap-pcm.h
3 *
4 * Copyright (C) 2008 Nokia Corporation
5 *
6 * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com>
7 * Peter Ujfalusi <peter.ujfalusi@ti.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25#ifndef __OMAP_PCM_H__
26#define __OMAP_PCM_H__
27
28struct snd_pcm_substream;
29
30struct omap_pcm_dma_data {
31 char *name; /* stream identifier */
32 int dma_req; /* DMA request line */
33 unsigned long port_addr; /* transmit/receive register */
34 void (*set_threshold)(struct snd_pcm_substream *substream);
35 int data_type; /* 8, 16, 32 (bits) or 0 to let omap-pcm
36 * to decide the sDMA data type */
37 int packet_size; /* packet size only in PACKET mode */
38};
39
40#endif
diff --git a/sound/soc/omap/omap-twl4030.c b/sound/soc/omap/omap-twl4030.c
index fd98509d0f49..2a9324f794d8 100644
--- a/sound/soc/omap/omap-twl4030.c
+++ b/sound/soc/omap/omap-twl4030.c
@@ -43,7 +43,6 @@
43#include <sound/jack.h> 43#include <sound/jack.h>
44 44
45#include "omap-mcbsp.h" 45#include "omap-mcbsp.h"
46#include "omap-pcm.h"
47 46
48struct omap_twl4030 { 47struct omap_twl4030 {
49 int jack_detect; /* board can detect jack events */ 48 int jack_detect; /* board can detect jack events */
diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c
index 805512f2555a..cf604a2faa18 100644
--- a/sound/soc/omap/omap3pandora.c
+++ b/sound/soc/omap/omap3pandora.c
@@ -34,7 +34,6 @@
34#include <linux/platform_data/asoc-ti-mcbsp.h> 34#include <linux/platform_data/asoc-ti-mcbsp.h>
35 35
36#include "omap-mcbsp.h" 36#include "omap-mcbsp.h"
37#include "omap-pcm.h"
38 37
39#define OMAP3_PANDORA_DAC_POWER_GPIO 118 38#define OMAP3_PANDORA_DAC_POWER_GPIO 118
40#define OMAP3_PANDORA_AMP_POWER_GPIO 14 39#define OMAP3_PANDORA_AMP_POWER_GPIO 14
@@ -80,12 +79,18 @@ static int omap3pandora_hw_params(struct snd_pcm_substream *substream,
80static int omap3pandora_dac_event(struct snd_soc_dapm_widget *w, 79static int omap3pandora_dac_event(struct snd_soc_dapm_widget *w,
81 struct snd_kcontrol *k, int event) 80 struct snd_kcontrol *k, int event)
82{ 81{
82 int ret;
83
83 /* 84 /*
84 * The PCM1773 DAC datasheet requires 1ms delay between switching 85 * The PCM1773 DAC datasheet requires 1ms delay between switching
85 * VCC power on/off and /PD pin high/low 86 * VCC power on/off and /PD pin high/low
86 */ 87 */
87 if (SND_SOC_DAPM_EVENT_ON(event)) { 88 if (SND_SOC_DAPM_EVENT_ON(event)) {
88 regulator_enable(omap3pandora_dac_reg); 89 ret = regulator_enable(omap3pandora_dac_reg);
90 if (ret) {
91 dev_err(w->dapm->dev, "Failed to power DAC: %d\n", ret);
92 return ret;
93 }
89 mdelay(1); 94 mdelay(1);
90 gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 1); 95 gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 1);
91 } else { 96 } else {
diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c
index 06ef8d67ed1c..d03e57da7708 100644
--- a/sound/soc/omap/osk5912.c
+++ b/sound/soc/omap/osk5912.c
@@ -33,7 +33,6 @@
33#include <linux/platform_data/asoc-ti-mcbsp.h> 33#include <linux/platform_data/asoc-ti-mcbsp.h>
34 34
35#include "omap-mcbsp.h" 35#include "omap-mcbsp.h"
36#include "omap-pcm.h"
37#include "../codecs/tlv320aic23.h" 36#include "../codecs/tlv320aic23.h"
38 37
39#define CODEC_CLOCK 12000000 38#define CODEC_CLOCK 12000000
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
index 3cd525748975..249cd230ad8f 100644
--- a/sound/soc/omap/rx51.c
+++ b/sound/soc/omap/rx51.c
@@ -37,7 +37,6 @@
37#include <asm/mach-types.h> 37#include <asm/mach-types.h>
38 38
39#include "omap-mcbsp.h" 39#include "omap-mcbsp.h"
40#include "omap-pcm.h"
41 40
42#define RX51_TVOUT_SEL_GPIO 40 41#define RX51_TVOUT_SEL_GPIO 40
43#define RX51_JACK_DETECT_GPIO 177 42#define RX51_JACK_DETECT_GPIO 177
diff --git a/sound/soc/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c
index 190eb0bccf5f..349930015264 100644
--- a/sound/soc/pxa/mmp-pcm.c
+++ b/sound/soc/pxa/mmp-pcm.c
@@ -118,9 +118,8 @@ static int mmp_pcm_open(struct snd_pcm_substream *substream)
118 struct snd_soc_pcm_runtime *rtd = substream->private_data; 118 struct snd_soc_pcm_runtime *rtd = substream->private_data;
119 struct platform_device *pdev = to_platform_device(rtd->platform->dev); 119 struct platform_device *pdev = to_platform_device(rtd->platform->dev);
120 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 120 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
121 struct mmp_dma_data *dma_data; 121 struct mmp_dma_data dma_data;
122 struct resource *r; 122 struct resource *r;
123 int ret;
124 123
125 r = platform_get_resource(pdev, IORESOURCE_DMA, substream->stream); 124 r = platform_get_resource(pdev, IORESOURCE_DMA, substream->stream);
126 if (!r) 125 if (!r)
@@ -128,33 +127,12 @@ static int mmp_pcm_open(struct snd_pcm_substream *substream)
128 127
129 snd_soc_set_runtime_hwparams(substream, 128 snd_soc_set_runtime_hwparams(substream,
130 &mmp_pcm_hardware[substream->stream]); 129 &mmp_pcm_hardware[substream->stream]);
131 dma_data = devm_kzalloc(&pdev->dev,
132 sizeof(struct mmp_dma_data), GFP_KERNEL);
133 if (dma_data == NULL)
134 return -ENOMEM;
135 130
136 dma_data->dma_res = r; 131 dma_data.dma_res = r;
137 dma_data->ssp_id = cpu_dai->id; 132 dma_data.ssp_id = cpu_dai->id;
138 133
139 ret = snd_dmaengine_pcm_open(substream, filter, dma_data); 134 return snd_dmaengine_pcm_open_request_chan(substream, filter,
140 if (ret) { 135 &dma_data);
141 devm_kfree(&pdev->dev, dma_data);
142 return ret;
143 }
144
145 snd_dmaengine_pcm_set_data(substream, dma_data);
146 return 0;
147}
148
149static int mmp_pcm_close(struct snd_pcm_substream *substream)
150{
151 struct mmp_dma_data *dma_data = snd_dmaengine_pcm_get_data(substream);
152 struct snd_soc_pcm_runtime *rtd = substream->private_data;
153 struct platform_device *pdev = to_platform_device(rtd->platform->dev);
154
155 snd_dmaengine_pcm_close(substream);
156 devm_kfree(&pdev->dev, dma_data);
157 return 0;
158} 136}
159 137
160static int mmp_pcm_mmap(struct snd_pcm_substream *substream, 138static int mmp_pcm_mmap(struct snd_pcm_substream *substream,
@@ -171,7 +149,7 @@ static int mmp_pcm_mmap(struct snd_pcm_substream *substream,
171 149
172struct snd_pcm_ops mmp_pcm_ops = { 150struct snd_pcm_ops mmp_pcm_ops = {
173 .open = mmp_pcm_open, 151 .open = mmp_pcm_open,
174 .close = mmp_pcm_close, 152 .close = snd_dmaengine_pcm_close_release_chan,
175 .ioctl = snd_pcm_lib_ioctl, 153 .ioctl = snd_pcm_lib_ioctl,
176 .hw_params = mmp_pcm_hw_params, 154 .hw_params = mmp_pcm_hw_params,
177 .trigger = snd_dmaengine_pcm_trigger, 155 .trigger = snd_dmaengine_pcm_trigger,
diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c
index 9140c4abafbc..a64779980177 100644
--- a/sound/soc/pxa/mmp-sspa.c
+++ b/sound/soc/pxa/mmp-sspa.c
@@ -405,6 +405,10 @@ struct snd_soc_dai_driver mmp_sspa_dai = {
405 .ops = &mmp_sspa_dai_ops, 405 .ops = &mmp_sspa_dai_ops,
406}; 406};
407 407
408static const struct snd_soc_component_driver mmp_sspa_component = {
409 .name = "mmp-sspa",
410};
411
408static int asoc_mmp_sspa_probe(struct platform_device *pdev) 412static int asoc_mmp_sspa_probe(struct platform_device *pdev)
409{ 413{
410 struct sspa_priv *priv; 414 struct sspa_priv *priv;
@@ -450,7 +454,8 @@ static int asoc_mmp_sspa_probe(struct platform_device *pdev)
450 priv->dai_fmt = (unsigned int) -1; 454 priv->dai_fmt = (unsigned int) -1;
451 platform_set_drvdata(pdev, priv); 455 platform_set_drvdata(pdev, priv);
452 456
453 return snd_soc_register_dai(&pdev->dev, &mmp_sspa_dai); 457 return snd_soc_register_component(&pdev->dev, &mmp_sspa_component,
458 &mmp_sspa_dai, 1);
454} 459}
455 460
456static int asoc_mmp_sspa_remove(struct platform_device *pdev) 461static int asoc_mmp_sspa_remove(struct platform_device *pdev)
@@ -460,7 +465,7 @@ static int asoc_mmp_sspa_remove(struct platform_device *pdev)
460 clk_disable(priv->audio_clk); 465 clk_disable(priv->audio_clk);
461 clk_put(priv->audio_clk); 466 clk_put(priv->audio_clk);
462 clk_put(priv->sysclk); 467 clk_put(priv->sysclk);
463 snd_soc_unregister_dai(&pdev->dev); 468 snd_soc_unregister_component(&pdev->dev);
464 return 0; 469 return 0;
465} 470}
466 471
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index d3eb0c2eec77..6f4dd7543e82 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -794,14 +794,19 @@ static struct snd_soc_dai_driver pxa_ssp_dai = {
794 .ops = &pxa_ssp_dai_ops, 794 .ops = &pxa_ssp_dai_ops,
795}; 795};
796 796
797static const struct snd_soc_component_driver pxa_ssp_component = {
798 .name = "pxa-ssp",
799};
800
797static int asoc_ssp_probe(struct platform_device *pdev) 801static int asoc_ssp_probe(struct platform_device *pdev)
798{ 802{
799 return snd_soc_register_dai(&pdev->dev, &pxa_ssp_dai); 803 return snd_soc_register_component(&pdev->dev, &pxa_ssp_component,
804 &pxa_ssp_dai, 1);
800} 805}
801 806
802static int asoc_ssp_remove(struct platform_device *pdev) 807static int asoc_ssp_remove(struct platform_device *pdev)
803{ 808{
804 snd_soc_unregister_dai(&pdev->dev); 809 snd_soc_unregister_component(&pdev->dev);
805 return 0; 810 return 0;
806} 811}
807 812
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index 4b0a009bd683..57ea8e6c5488 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -47,6 +47,7 @@ struct snd_ac97_bus_ops soc_ac97_ops = {
47 .warm_reset = pxa2xx_ac97_warm_reset, 47 .warm_reset = pxa2xx_ac97_warm_reset,
48 .reset = pxa2xx_ac97_cold_reset, 48 .reset = pxa2xx_ac97_cold_reset,
49}; 49};
50EXPORT_SYMBOL_GPL(soc_ac97_ops);
50 51
51static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = { 52static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = {
52 .name = "AC97 PCM Stereo out", 53 .name = "AC97 PCM Stereo out",
@@ -232,7 +233,9 @@ static struct snd_soc_dai_driver pxa_ac97_dai_driver[] = {
232}, 233},
233}; 234};
234 235
235EXPORT_SYMBOL_GPL(soc_ac97_ops); 236static const struct snd_soc_component_driver pxa_ac97_component = {
237 .name = "pxa-ac97",
238};
236 239
237static int pxa2xx_ac97_dev_probe(struct platform_device *pdev) 240static int pxa2xx_ac97_dev_probe(struct platform_device *pdev)
238{ 241{
@@ -245,13 +248,13 @@ static int pxa2xx_ac97_dev_probe(struct platform_device *pdev)
245 * driver to do interesting things with the clocking to get us up 248 * driver to do interesting things with the clocking to get us up
246 * and running. 249 * and running.
247 */ 250 */
248 return snd_soc_register_dais(&pdev->dev, pxa_ac97_dai_driver, 251 return snd_soc_register_component(&pdev->dev, &pxa_ac97_component,
249 ARRAY_SIZE(pxa_ac97_dai_driver)); 252 pxa_ac97_dai_driver, ARRAY_SIZE(pxa_ac97_dai_driver));
250} 253}
251 254
252static int pxa2xx_ac97_dev_remove(struct platform_device *pdev) 255static int pxa2xx_ac97_dev_remove(struct platform_device *pdev)
253{ 256{
254 snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(pxa_ac97_dai_driver)); 257 snd_soc_unregister_component(&pdev->dev);
255 return 0; 258 return 0;
256} 259}
257 260
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index 6b1a06f67564..f7ca71664112 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -360,14 +360,19 @@ static struct snd_soc_dai_driver pxa_i2s_dai = {
360 .symmetric_rates = 1, 360 .symmetric_rates = 1,
361}; 361};
362 362
363static const struct snd_soc_component_driver pxa_i2s_component = {
364 .name = "pxa-i2s",
365};
366
363static int pxa2xx_i2s_drv_probe(struct platform_device *pdev) 367static int pxa2xx_i2s_drv_probe(struct platform_device *pdev)
364{ 368{
365 return snd_soc_register_dai(&pdev->dev, &pxa_i2s_dai); 369 return snd_soc_register_component(&pdev->dev, &pxa_i2s_component,
370 &pxa_i2s_dai, 1);
366} 371}
367 372
368static int pxa2xx_i2s_drv_remove(struct platform_device *pdev) 373static int pxa2xx_i2s_drv_remove(struct platform_device *pdev)
369{ 374{
370 snd_soc_unregister_dai(&pdev->dev); 375 snd_soc_unregister_component(&pdev->dev);
371 return 0; 376 return 0;
372} 377}
373 378
diff --git a/sound/soc/s6000/s6000-i2s.c b/sound/soc/s6000/s6000-i2s.c
index fee4d477a49c..73bb99f0109a 100644
--- a/sound/soc/s6000/s6000-i2s.c
+++ b/sound/soc/s6000/s6000-i2s.c
@@ -436,6 +436,10 @@ static struct snd_soc_dai_driver s6000_i2s_dai = {
436 .ops = &s6000_i2s_dai_ops, 436 .ops = &s6000_i2s_dai_ops,
437}; 437};
438 438
439static const struct snd_soc_component_driver s6000_i2s_component = {
440 .name = "s6000-i2s",
441};
442
439static int s6000_i2s_probe(struct platform_device *pdev) 443static int s6000_i2s_probe(struct platform_device *pdev)
440{ 444{
441 struct s6000_i2s_dev *dev; 445 struct s6000_i2s_dev *dev;
@@ -543,7 +547,8 @@ static int s6000_i2s_probe(struct platform_device *pdev)
543 S6_I2S_INT_UNDERRUN | 547 S6_I2S_INT_UNDERRUN |
544 S6_I2S_INT_OVERRUN); 548 S6_I2S_INT_OVERRUN);
545 549
546 ret = snd_soc_register_dai(&pdev->dev, &s6000_i2s_dai); 550 ret = snd_soc_register_component(&pdev->dev, &s6000_i2s_component,
551 &s6000_i2s_dai, 1);
547 if (ret) 552 if (ret)
548 goto err_release_dev; 553 goto err_release_dev;
549 554
@@ -572,7 +577,7 @@ static void s6000_i2s_remove(struct platform_device *pdev)
572 struct resource *region; 577 struct resource *region;
573 void __iomem *mmio = dev->scbbase; 578 void __iomem *mmio = dev->scbbase;
574 579
575 snd_soc_unregister_dai(&pdev->dev); 580 snd_soc_unregister_component(&pdev->dev);
576 581
577 s6000_i2s_stop_channel(dev, 0); 582 s6000_i2s_stop_channel(dev, 0);
578 s6000_i2s_stop_channel(dev, 1); 583 s6000_i2s_stop_channel(dev, 1);
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig
index 90e7e6653233..475fb0d8b3c6 100644
--- a/sound/soc/samsung/Kconfig
+++ b/sound/soc/samsung/Kconfig
@@ -35,11 +35,10 @@ config SND_SAMSUNG_I2S
35 tristate 35 tristate
36 36
37config SND_SOC_SAMSUNG_NEO1973_WM8753 37config SND_SOC_SAMSUNG_NEO1973_WM8753
38 tristate "Audio support for Openmoko Neo1973 Smartphones (GTA01/GTA02)" 38 tristate "Audio support for Openmoko Neo1973 Smartphones (GTA02)"
39 depends on SND_SOC_SAMSUNG && (MACH_NEO1973_GTA01 || MACH_NEO1973_GTA02) 39 depends on SND_SOC_SAMSUNG && MACH_NEO1973_GTA02
40 select SND_S3C24XX_I2S 40 select SND_S3C24XX_I2S
41 select SND_SOC_WM8753 41 select SND_SOC_WM8753
42 select SND_SOC_LM4857 if MACH_NEO1973_GTA01
43 select SND_SOC_DFBMCS320 42 select SND_SOC_DFBMCS320
44 help 43 help
45 Say Y here to enable audio support for the Openmoko Neo1973 44 Say Y here to enable audio support for the Openmoko Neo1973
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c
index 0df3c5644cfa..cb88ead98917 100644
--- a/sound/soc/samsung/ac97.c
+++ b/sound/soc/samsung/ac97.c
@@ -20,7 +20,7 @@
20#include <sound/soc.h> 20#include <sound/soc.h>
21 21
22#include <mach/dma.h> 22#include <mach/dma.h>
23#include <plat/regs-ac97.h> 23#include "regs-ac97.h"
24#include <linux/platform_data/asoc-s3c.h> 24#include <linux/platform_data/asoc-s3c.h>
25 25
26#include "dma.h" 26#include "dma.h"
@@ -370,6 +370,10 @@ static struct snd_soc_dai_driver s3c_ac97_dai[] = {
370 }, 370 },
371}; 371};
372 372
373static const struct snd_soc_component_driver s3c_ac97_component = {
374 .name = "s3c-ac97",
375};
376
373static int s3c_ac97_probe(struct platform_device *pdev) 377static int s3c_ac97_probe(struct platform_device *pdev)
374{ 378{
375 struct resource *mem_res, *dmatx_res, *dmarx_res, *dmamic_res, *irq_res; 379 struct resource *mem_res, *dmatx_res, *dmarx_res, *dmamic_res, *irq_res;
@@ -457,8 +461,8 @@ static int s3c_ac97_probe(struct platform_device *pdev)
457 goto err4; 461 goto err4;
458 } 462 }
459 463
460 ret = snd_soc_register_dais(&pdev->dev, s3c_ac97_dai, 464 ret = snd_soc_register_component(&pdev->dev, &s3c_ac97_component,
461 ARRAY_SIZE(s3c_ac97_dai)); 465 s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai));
462 if (ret) 466 if (ret)
463 goto err5; 467 goto err5;
464 468
@@ -470,7 +474,7 @@ static int s3c_ac97_probe(struct platform_device *pdev)
470 474
471 return 0; 475 return 0;
472err6: 476err6:
473 snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(s3c_ac97_dai)); 477 snd_soc_unregister_component(&pdev->dev);
474err5: 478err5:
475 free_irq(irq_res->start, NULL); 479 free_irq(irq_res->start, NULL);
476err4: 480err4:
@@ -490,7 +494,7 @@ static int s3c_ac97_remove(struct platform_device *pdev)
490 struct resource *mem_res, *irq_res; 494 struct resource *mem_res, *irq_res;
491 495
492 asoc_dma_platform_unregister(&pdev->dev); 496 asoc_dma_platform_unregister(&pdev->dev);
493 snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(s3c_ac97_dai)); 497 snd_soc_unregister_component(&pdev->dev);
494 498
495 irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 499 irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
496 if (irq_res) 500 if (irq_res)
diff --git a/sound/soc/samsung/goni_wm8994.c b/sound/soc/samsung/goni_wm8994.c
index d37ede58e0a8..415ad81999c4 100644
--- a/sound/soc/samsung/goni_wm8994.c
+++ b/sound/soc/samsung/goni_wm8994.c
@@ -218,6 +218,10 @@ static struct snd_soc_dai_driver voice_dai = {
218 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 218 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
219}; 219};
220 220
221static const struct snd_soc_component_driver voice_component = {
222 .name = "goni-voice",
223};
224
221static struct snd_soc_ops goni_voice_ops = { 225static struct snd_soc_ops goni_voice_ops = {
222 .hw_params = goni_voice_hw_params, 226 .hw_params = goni_voice_hw_params,
223}; 227};
@@ -270,7 +274,8 @@ static int __init goni_init(void)
270 return -ENOMEM; 274 return -ENOMEM;
271 275
272 /* register voice DAI here */ 276 /* register voice DAI here */
273 ret = snd_soc_register_dai(&goni_snd_device->dev, &voice_dai); 277 ret = snd_soc_register_component(&goni_snd_device->dev, &voice_component,
278 &voice_dai, 1);
274 if (ret) { 279 if (ret) {
275 platform_device_put(goni_snd_device); 280 platform_device_put(goni_snd_device);
276 return ret; 281 return ret;
@@ -280,7 +285,7 @@ static int __init goni_init(void)
280 ret = platform_device_add(goni_snd_device); 285 ret = platform_device_add(goni_snd_device);
281 286
282 if (ret) { 287 if (ret) {
283 snd_soc_unregister_dai(&goni_snd_device->dev); 288 snd_soc_unregister_component(&goni_snd_device->dev);
284 platform_device_put(goni_snd_device); 289 platform_device_put(goni_snd_device);
285 } 290 }
286 291
@@ -289,7 +294,7 @@ static int __init goni_init(void)
289 294
290static void __exit goni_exit(void) 295static void __exit goni_exit(void)
291{ 296{
292 snd_soc_unregister_dai(&goni_snd_device->dev); 297 snd_soc_unregister_component(&goni_snd_device->dev);
293 platform_device_unregister(goni_snd_device); 298 platform_device_unregister(goni_snd_device);
294} 299}
295 300
diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c
index 15a3817aa5c8..fa91376e323d 100644
--- a/sound/soc/samsung/h1940_uda1380.c
+++ b/sound/soc/samsung/h1940_uda1380.c
@@ -20,7 +20,7 @@
20#include <sound/soc.h> 20#include <sound/soc.h>
21#include <sound/jack.h> 21#include <sound/jack.h>
22 22
23#include <plat/regs-iis.h> 23#include "regs-iis.h"
24#include <asm/mach-types.h> 24#include <asm/mach-types.h>
25 25
26#include "s3c24xx-i2s.h" 26#include "s3c24xx-i2s.h"
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index 6bbeb0bf1a73..82ebb1a51479 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -963,6 +963,10 @@ static const struct snd_soc_dai_ops samsung_i2s_dai_ops = {
963 .delay = i2s_delay, 963 .delay = i2s_delay,
964}; 964};
965 965
966static const struct snd_soc_component_driver samsung_i2s_component = {
967 .name = "samsung-i2s",
968};
969
966#define SAMSUNG_I2S_RATES SNDRV_PCM_RATE_8000_96000 970#define SAMSUNG_I2S_RATES SNDRV_PCM_RATE_8000_96000
967 971
968#define SAMSUNG_I2S_FMTS (SNDRV_PCM_FMTBIT_S8 | \ 972#define SAMSUNG_I2S_FMTS (SNDRV_PCM_FMTBIT_S8 | \
@@ -1114,8 +1118,9 @@ static int samsung_i2s_probe(struct platform_device *pdev)
1114 dev_err(&pdev->dev, "Unable to get drvdata\n"); 1118 dev_err(&pdev->dev, "Unable to get drvdata\n");
1115 return -EFAULT; 1119 return -EFAULT;
1116 } 1120 }
1117 snd_soc_register_dai(&sec_dai->pdev->dev, 1121 snd_soc_register_component(&sec_dai->pdev->dev,
1118 &sec_dai->i2s_dai_drv); 1122 &samsung_i2s_component,
1123 &sec_dai->i2s_dai_drv, 1);
1119 asoc_dma_platform_register(&pdev->dev); 1124 asoc_dma_platform_register(&pdev->dev);
1120 return 0; 1125 return 0;
1121 } 1126 }
@@ -1244,7 +1249,8 @@ static int samsung_i2s_probe(struct platform_device *pdev)
1244 } 1249 }
1245 } 1250 }
1246 1251
1247 snd_soc_register_dai(&pri_dai->pdev->dev, &pri_dai->i2s_dai_drv); 1252 snd_soc_register_component(&pri_dai->pdev->dev, &samsung_i2s_component,
1253 &pri_dai->i2s_dai_drv, 1);
1248 1254
1249 pm_runtime_enable(&pdev->dev); 1255 pm_runtime_enable(&pdev->dev);
1250 1256
@@ -1283,7 +1289,7 @@ static int samsung_i2s_remove(struct platform_device *pdev)
1283 i2s->sec_dai = NULL; 1289 i2s->sec_dai = NULL;
1284 1290
1285 asoc_dma_platform_unregister(&pdev->dev); 1291 asoc_dma_platform_unregister(&pdev->dev);
1286 snd_soc_unregister_dai(&pdev->dev); 1292 snd_soc_unregister_component(&pdev->dev);
1287 1293
1288 return 0; 1294 return 0;
1289} 1295}
@@ -1298,7 +1304,7 @@ static struct platform_device_id samsung_i2s_driver_ids[] = {
1298 }, 1304 },
1299 {}, 1305 {},
1300}; 1306};
1301MODULE_DEVICE_TABLE(platform, samsung-i2s-driver-ids); 1307MODULE_DEVICE_TABLE(platform, samsung_i2s_driver_ids);
1302 1308
1303#ifdef CONFIG_OF 1309#ifdef CONFIG_OF
1304static struct samsung_i2s_dai_data samsung_i2s_dai_data_array[] = { 1310static struct samsung_i2s_dai_data samsung_i2s_dai_data_array[] = {
diff --git a/sound/soc/samsung/idma.c b/sound/soc/samsung/idma.c
index a07950b0c8ce..6e5fed30aa27 100644
--- a/sound/soc/samsung/idma.c
+++ b/sound/soc/samsung/idma.c
@@ -68,6 +68,8 @@ static struct idma_info {
68 dma_addr_t lp_tx_addr; 68 dma_addr_t lp_tx_addr;
69} idma; 69} idma;
70 70
71static int idma_irq;
72
71static void idma_getpos(dma_addr_t *src) 73static void idma_getpos(dma_addr_t *src)
72{ 74{
73 *src = idma.lp_tx_addr + 75 *src = idma.lp_tx_addr +
@@ -305,7 +307,7 @@ static int idma_open(struct snd_pcm_substream *substream)
305 if (prtd == NULL) 307 if (prtd == NULL)
306 return -ENOMEM; 308 return -ENOMEM;
307 309
308 ret = request_irq(IRQ_I2S0, iis_irq, 0, "i2s", prtd); 310 ret = request_irq(idma_irq, iis_irq, 0, "i2s", prtd);
309 if (ret < 0) { 311 if (ret < 0) {
310 pr_err("fail to claim i2s irq , ret = %d\n", ret); 312 pr_err("fail to claim i2s irq , ret = %d\n", ret);
311 kfree(prtd); 313 kfree(prtd);
@@ -324,7 +326,7 @@ static int idma_close(struct snd_pcm_substream *substream)
324 struct snd_pcm_runtime *runtime = substream->runtime; 326 struct snd_pcm_runtime *runtime = substream->runtime;
325 struct idma_ctrl *prtd = runtime->private_data; 327 struct idma_ctrl *prtd = runtime->private_data;
326 328
327 free_irq(IRQ_I2S0, prtd); 329 free_irq(idma_irq, prtd);
328 330
329 if (!prtd) 331 if (!prtd)
330 pr_err("idma_close called with prtd == NULL\n"); 332 pr_err("idma_close called with prtd == NULL\n");
@@ -409,6 +411,7 @@ void idma_reg_addr_init(void __iomem *regs, dma_addr_t addr)
409 idma.regs = regs; 411 idma.regs = regs;
410 idma.lp_tx_addr = addr; 412 idma.lp_tx_addr = addr;
411} 413}
414EXPORT_SYMBOL_GPL(idma_reg_addr_init);
412 415
413static struct snd_soc_platform_driver asoc_idma_platform = { 416static struct snd_soc_platform_driver asoc_idma_platform = {
414 .ops = &idma_ops, 417 .ops = &idma_ops,
@@ -418,6 +421,10 @@ static struct snd_soc_platform_driver asoc_idma_platform = {
418 421
419static int asoc_idma_platform_probe(struct platform_device *pdev) 422static int asoc_idma_platform_probe(struct platform_device *pdev)
420{ 423{
424 idma_irq = platform_get_irq(pdev, 0);
425 if (idma_irq < 0)
426 return idma_irq;
427
421 return snd_soc_register_platform(&pdev->dev, &asoc_idma_platform); 428 return snd_soc_register_platform(&pdev->dev, &asoc_idma_platform);
422} 429}
423 430
diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c
index a301d8cfaa34..e591c386917a 100644
--- a/sound/soc/samsung/neo1973_wm8753.c
+++ b/sound/soc/samsung/neo1973_wm8753.c
@@ -21,8 +21,7 @@
21#include <sound/soc.h> 21#include <sound/soc.h>
22 22
23#include <asm/mach-types.h> 23#include <asm/mach-types.h>
24#include <plat/regs-iis.h> 24#include "regs-iis.h"
25#include <mach/gta02.h>
26 25
27#include "../codecs/wm8753.h" 26#include "../codecs/wm8753.h"
28#include "s3c24xx-i2s.h" 27#include "s3c24xx-i2s.h"
diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c
index 13bab79ad93d..1566afe9ef52 100644
--- a/sound/soc/samsung/pcm.c
+++ b/sound/soc/samsung/pcm.c
@@ -490,6 +490,10 @@ static struct snd_soc_dai_driver s3c_pcm_dai[] = {
490 }, 490 },
491}; 491};
492 492
493static const struct snd_soc_component_driver s3c_pcm_component = {
494 .name = "s3c-pcm",
495};
496
493static int s3c_pcm_dev_probe(struct platform_device *pdev) 497static int s3c_pcm_dev_probe(struct platform_device *pdev)
494{ 498{
495 struct s3c_pcm_info *pcm; 499 struct s3c_pcm_info *pcm;
@@ -583,7 +587,8 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev)
583 587
584 pm_runtime_enable(&pdev->dev); 588 pm_runtime_enable(&pdev->dev);
585 589
586 ret = snd_soc_register_dai(&pdev->dev, &s3c_pcm_dai[pdev->id]); 590 ret = snd_soc_register_component(&pdev->dev, &s3c_pcm_component,
591 &s3c_pcm_dai[pdev->id], 1);
587 if (ret != 0) { 592 if (ret != 0) {
588 dev_err(&pdev->dev, "failed to get register DAI: %d\n", ret); 593 dev_err(&pdev->dev, "failed to get register DAI: %d\n", ret);
589 goto err5; 594 goto err5;
@@ -598,7 +603,7 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev)
598 return 0; 603 return 0;
599 604
600err6: 605err6:
601 snd_soc_unregister_dai(&pdev->dev); 606 snd_soc_unregister_component(&pdev->dev);
602err5: 607err5:
603 clk_disable_unprepare(pcm->pclk); 608 clk_disable_unprepare(pcm->pclk);
604 clk_put(pcm->pclk); 609 clk_put(pcm->pclk);
@@ -619,7 +624,7 @@ static int s3c_pcm_dev_remove(struct platform_device *pdev)
619 struct resource *mem_res; 624 struct resource *mem_res;
620 625
621 asoc_dma_platform_unregister(&pdev->dev); 626 asoc_dma_platform_unregister(&pdev->dev);
622 snd_soc_unregister_dai(&pdev->dev); 627 snd_soc_unregister_component(&pdev->dev);
623 628
624 pm_runtime_disable(&pdev->dev); 629 pm_runtime_disable(&pdev->dev);
625 630
diff --git a/sound/soc/samsung/regs-ac97.h b/sound/soc/samsung/regs-ac97.h
new file mode 100644
index 000000000000..c3878f7acb83
--- /dev/null
+++ b/sound/soc/samsung/regs-ac97.h
@@ -0,0 +1,67 @@
1/* arch/arm/mach-s3c2410/include/mach/regs-ac97.h
2 *
3 * Copyright (c) 2006 Simtec Electronics <linux@simtec.co.uk>
4 * http://www.simtec.co.uk/products/SWLINUX/
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * S3C2440 AC97 Controller
11*/
12
13#ifndef __ASM_ARCH_REGS_AC97_H
14#define __ASM_ARCH_REGS_AC97_H __FILE__
15
16#define S3C_AC97_GLBCTRL (0x00)
17
18#define S3C_AC97_GLBCTRL_CODECREADYIE (1<<22)
19#define S3C_AC97_GLBCTRL_PCMOUTURIE (1<<21)
20#define S3C_AC97_GLBCTRL_PCMINORIE (1<<20)
21#define S3C_AC97_GLBCTRL_MICINORIE (1<<19)
22#define S3C_AC97_GLBCTRL_PCMOUTTIE (1<<18)
23#define S3C_AC97_GLBCTRL_PCMINTIE (1<<17)
24#define S3C_AC97_GLBCTRL_MICINTIE (1<<16)
25#define S3C_AC97_GLBCTRL_PCMOUTTM_OFF (0<<12)
26#define S3C_AC97_GLBCTRL_PCMOUTTM_PIO (1<<12)
27#define S3C_AC97_GLBCTRL_PCMOUTTM_DMA (2<<12)
28#define S3C_AC97_GLBCTRL_PCMOUTTM_MASK (3<<12)
29#define S3C_AC97_GLBCTRL_PCMINTM_OFF (0<<10)
30#define S3C_AC97_GLBCTRL_PCMINTM_PIO (1<<10)
31#define S3C_AC97_GLBCTRL_PCMINTM_DMA (2<<10)
32#define S3C_AC97_GLBCTRL_PCMINTM_MASK (3<<10)
33#define S3C_AC97_GLBCTRL_MICINTM_OFF (0<<8)
34#define S3C_AC97_GLBCTRL_MICINTM_PIO (1<<8)
35#define S3C_AC97_GLBCTRL_MICINTM_DMA (2<<8)
36#define S3C_AC97_GLBCTRL_MICINTM_MASK (3<<8)
37#define S3C_AC97_GLBCTRL_TRANSFERDATAENABLE (1<<3)
38#define S3C_AC97_GLBCTRL_ACLINKON (1<<2)
39#define S3C_AC97_GLBCTRL_WARMRESET (1<<1)
40#define S3C_AC97_GLBCTRL_COLDRESET (1<<0)
41
42#define S3C_AC97_GLBSTAT (0x04)
43
44#define S3C_AC97_GLBSTAT_CODECREADY (1<<22)
45#define S3C_AC97_GLBSTAT_PCMOUTUR (1<<21)
46#define S3C_AC97_GLBSTAT_PCMINORI (1<<20)
47#define S3C_AC97_GLBSTAT_MICINORI (1<<19)
48#define S3C_AC97_GLBSTAT_PCMOUTTI (1<<18)
49#define S3C_AC97_GLBSTAT_PCMINTI (1<<17)
50#define S3C_AC97_GLBSTAT_MICINTI (1<<16)
51#define S3C_AC97_GLBSTAT_MAINSTATE_IDLE (0<<0)
52#define S3C_AC97_GLBSTAT_MAINSTATE_INIT (1<<0)
53#define S3C_AC97_GLBSTAT_MAINSTATE_READY (2<<0)
54#define S3C_AC97_GLBSTAT_MAINSTATE_ACTIVE (3<<0)
55#define S3C_AC97_GLBSTAT_MAINSTATE_LP (4<<0)
56#define S3C_AC97_GLBSTAT_MAINSTATE_WARM (5<<0)
57
58#define S3C_AC97_CODEC_CMD (0x08)
59
60#define S3C_AC97_CODEC_CMD_READ (1<<23)
61
62#define S3C_AC97_STAT (0x0c)
63#define S3C_AC97_PCM_ADDR (0x10)
64#define S3C_AC97_PCM_DATA (0x18)
65#define S3C_AC97_MIC_DATA (0x1C)
66
67#endif /* __ASM_ARCH_REGS_AC97_H */
diff --git a/sound/soc/samsung/regs-iis.h b/sound/soc/samsung/regs-iis.h
new file mode 100644
index 000000000000..a18d35e7a735
--- /dev/null
+++ b/sound/soc/samsung/regs-iis.h
@@ -0,0 +1,70 @@
1/* arch/arm/plat-samsung/include/plat/regs-iis.h
2 *
3 * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
4 * http://www.simtec.co.uk/products/SWLINUX/
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * S3C2410 IIS register definition
11*/
12
13#ifndef __ASM_ARCH_REGS_IIS_H
14#define __ASM_ARCH_REGS_IIS_H
15
16#define S3C2410_IISCON (0x00)
17
18#define S3C2410_IISCON_LRINDEX (1 << 8)
19#define S3C2410_IISCON_TXFIFORDY (1 << 7)
20#define S3C2410_IISCON_RXFIFORDY (1 << 6)
21#define S3C2410_IISCON_TXDMAEN (1 << 5)
22#define S3C2410_IISCON_RXDMAEN (1 << 4)
23#define S3C2410_IISCON_TXIDLE (1 << 3)
24#define S3C2410_IISCON_RXIDLE (1 << 2)
25#define S3C2410_IISCON_PSCEN (1 << 1)
26#define S3C2410_IISCON_IISEN (1 << 0)
27
28#define S3C2410_IISMOD (0x04)
29
30#define S3C2440_IISMOD_MPLL (1 << 9)
31#define S3C2410_IISMOD_SLAVE (1 << 8)
32#define S3C2410_IISMOD_NOXFER (0 << 6)
33#define S3C2410_IISMOD_RXMODE (1 << 6)
34#define S3C2410_IISMOD_TXMODE (2 << 6)
35#define S3C2410_IISMOD_TXRXMODE (3 << 6)
36#define S3C2410_IISMOD_LR_LLOW (0 << 5)
37#define S3C2410_IISMOD_LR_RLOW (1 << 5)
38#define S3C2410_IISMOD_IIS (0 << 4)
39#define S3C2410_IISMOD_MSB (1 << 4)
40#define S3C2410_IISMOD_8BIT (0 << 3)
41#define S3C2410_IISMOD_16BIT (1 << 3)
42#define S3C2410_IISMOD_BITMASK (1 << 3)
43#define S3C2410_IISMOD_256FS (0 << 2)
44#define S3C2410_IISMOD_384FS (1 << 2)
45#define S3C2410_IISMOD_16FS (0 << 0)
46#define S3C2410_IISMOD_32FS (1 << 0)
47#define S3C2410_IISMOD_48FS (2 << 0)
48#define S3C2410_IISMOD_FS_MASK (3 << 0)
49
50#define S3C2410_IISPSR (0x08)
51
52#define S3C2410_IISPSR_INTMASK (31 << 5)
53#define S3C2410_IISPSR_INTSHIFT (5)
54#define S3C2410_IISPSR_EXTMASK (31 << 0)
55#define S3C2410_IISPSR_EXTSHFIT (0)
56
57#define S3C2410_IISFCON (0x0c)
58
59#define S3C2410_IISFCON_TXDMA (1 << 15)
60#define S3C2410_IISFCON_RXDMA (1 << 14)
61#define S3C2410_IISFCON_TXENABLE (1 << 13)
62#define S3C2410_IISFCON_RXENABLE (1 << 12)
63#define S3C2410_IISFCON_TXMASK (0x3f << 6)
64#define S3C2410_IISFCON_TXSHIFT (6)
65#define S3C2410_IISFCON_RXMASK (0x3f)
66#define S3C2410_IISFCON_RXSHIFT (0)
67
68#define S3C2410_IISFIFO (0x10)
69
70#endif /* __ASM_ARCH_REGS_IIS_H */
diff --git a/sound/soc/samsung/rx1950_uda1380.c b/sound/soc/samsung/rx1950_uda1380.c
index a5826ea9cad6..704460a37005 100644
--- a/sound/soc/samsung/rx1950_uda1380.c
+++ b/sound/soc/samsung/rx1950_uda1380.c
@@ -24,7 +24,7 @@
24#include <sound/soc.h> 24#include <sound/soc.h>
25#include <sound/jack.h> 25#include <sound/jack.h>
26 26
27#include <plat/regs-iis.h> 27#include "regs-iis.h"
28#include <asm/mach-types.h> 28#include <asm/mach-types.h>
29 29
30#include "s3c24xx-i2s.h" 30#include "s3c24xx-i2s.h"
diff --git a/sound/soc/samsung/s3c-i2s-v2.c b/sound/soc/samsung/s3c-i2s-v2.c
index 7a73380b3560..20e98d1dded2 100644
--- a/sound/soc/samsung/s3c-i2s-v2.c
+++ b/sound/soc/samsung/s3c-i2s-v2.c
@@ -731,8 +731,9 @@ static int s3c2412_i2s_resume(struct snd_soc_dai *dai)
731#define s3c2412_i2s_resume NULL 731#define s3c2412_i2s_resume NULL
732#endif 732#endif
733 733
734int s3c_i2sv2_register_dai(struct device *dev, int id, 734int s3c_i2sv2_register_component(struct device *dev, int id,
735 struct snd_soc_dai_driver *drv) 735 struct snd_soc_component_driver *cmp_drv,
736 struct snd_soc_dai_driver *dai_drv)
736{ 737{
737 struct snd_soc_dai_ops *ops = drv->ops; 738 struct snd_soc_dai_ops *ops = drv->ops;
738 739
@@ -750,8 +751,8 @@ int s3c_i2sv2_register_dai(struct device *dev, int id,
750 drv->suspend = s3c2412_i2s_suspend; 751 drv->suspend = s3c2412_i2s_suspend;
751 drv->resume = s3c2412_i2s_resume; 752 drv->resume = s3c2412_i2s_resume;
752 753
753 return snd_soc_register_dai(dev, drv); 754 return snd_soc_register_component(dev, cmp_drv, dai_drv, 1);
754} 755}
755EXPORT_SYMBOL_GPL(s3c_i2sv2_register_dai); 756EXPORT_SYMBOL_GPL(s3c_i2sv2_register_component);
756 757
757MODULE_LICENSE("GPL"); 758MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/s3c-i2s-v2.h b/sound/soc/samsung/s3c-i2s-v2.h
index f8297d9bb8a3..90abab364b49 100644
--- a/sound/soc/samsung/s3c-i2s-v2.h
+++ b/sound/soc/samsung/s3c-i2s-v2.h
@@ -92,7 +92,7 @@ extern int s3c_i2sv2_probe(struct snd_soc_dai *dai,
92 unsigned long base); 92 unsigned long base);
93 93
94/** 94/**
95 * s3c_i2sv2_register_dai - register dai with soc core 95 * s3c_i2sv2_register_component - register component and dai with soc core
96 * @dev: DAI device 96 * @dev: DAI device
97 * @id: DAI ID 97 * @id: DAI ID
98 * @drv: The driver structure to register 98 * @drv: The driver structure to register
@@ -100,7 +100,8 @@ extern int s3c_i2sv2_probe(struct snd_soc_dai *dai,
100 * Fill in any missing fields and then register the given dai with the 100 * Fill in any missing fields and then register the given dai with the
101 * soc core. 101 * soc core.
102 */ 102 */
103extern int s3c_i2sv2_register_dai(struct device *dev, int id, 103extern int s3c_i2sv2_register_component(struct device *dev, int id,
104 struct snd_soc_dai_driver *drv); 104 struct snd_soc_component_driver *cmp_drv,
105 struct snd_soc_dai_driver *dai_drv);
105 106
106#endif /* __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H */ 107#endif /* __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H */
diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c
index 221337716393..47e23864ea72 100644
--- a/sound/soc/samsung/s3c2412-i2s.c
+++ b/sound/soc/samsung/s3c2412-i2s.c
@@ -160,11 +160,17 @@ static struct snd_soc_dai_driver s3c2412_i2s_dai = {
160 .ops = &s3c2412_i2s_dai_ops, 160 .ops = &s3c2412_i2s_dai_ops,
161}; 161};
162 162
163static const struct snd_soc_component_driver s3c2412_i2s_component = {
164 .name = "s3c2412-i2s",
165};
166
163static int s3c2412_iis_dev_probe(struct platform_device *pdev) 167static int s3c2412_iis_dev_probe(struct platform_device *pdev)
164{ 168{
165 int ret = 0; 169 int ret = 0;
166 170
167 ret = s3c_i2sv2_register_dai(&pdev->dev, -1, &s3c2412_i2s_dai); 171 ret = s3c_i2sv2_register_component(&pdev->dev, -1,
172 &s3c2412_i2s_component,
173 &s3c2412_i2s_dai);
168 if (ret) { 174 if (ret) {
169 pr_err("failed to register the dai\n"); 175 pr_err("failed to register the dai\n");
170 return ret; 176 return ret;
@@ -178,14 +184,14 @@ static int s3c2412_iis_dev_probe(struct platform_device *pdev)
178 184
179 return 0; 185 return 0;
180err: 186err:
181 snd_soc_unregister_dai(&pdev->dev); 187 snd_soc_unregister_component(&pdev->dev);
182 return ret; 188 return ret;
183} 189}
184 190
185static int s3c2412_iis_dev_remove(struct platform_device *pdev) 191static int s3c2412_iis_dev_remove(struct platform_device *pdev)
186{ 192{
187 asoc_dma_platform_unregister(&pdev->dev); 193 asoc_dma_platform_unregister(&pdev->dev);
188 snd_soc_unregister_dai(&pdev->dev); 194 snd_soc_unregister_component(&pdev->dev);
189 return 0; 195 return 0;
190} 196}
191 197
diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c
index 13f6dd1ceb00..8b3414551a62 100644
--- a/sound/soc/samsung/s3c24xx-i2s.c
+++ b/sound/soc/samsung/s3c24xx-i2s.c
@@ -24,7 +24,7 @@
24#include <sound/pcm_params.h> 24#include <sound/pcm_params.h>
25 25
26#include <mach/dma.h> 26#include <mach/dma.h>
27#include <plat/regs-iis.h> 27#include "regs-iis.h"
28 28
29#include "dma.h" 29#include "dma.h"
30#include "s3c24xx-i2s.h" 30#include "s3c24xx-i2s.h"
@@ -465,11 +465,16 @@ static struct snd_soc_dai_driver s3c24xx_i2s_dai = {
465 .ops = &s3c24xx_i2s_dai_ops, 465 .ops = &s3c24xx_i2s_dai_ops,
466}; 466};
467 467
468static const struct snd_soc_component_driver s3c24xx_i2s_component = {
469 .name = "s3c24xx-i2s",
470};
471
468static int s3c24xx_iis_dev_probe(struct platform_device *pdev) 472static int s3c24xx_iis_dev_probe(struct platform_device *pdev)
469{ 473{
470 int ret = 0; 474 int ret = 0;
471 475
472 ret = snd_soc_register_dai(&pdev->dev, &s3c24xx_i2s_dai); 476 ret = snd_soc_register_component(&pdev->dev, &s3c24xx_i2s_component,
477 &s3c24xx_i2s_dai, 1);
473 if (ret) { 478 if (ret) {
474 pr_err("failed to register the dai\n"); 479 pr_err("failed to register the dai\n");
475 return ret; 480 return ret;
@@ -483,14 +488,14 @@ static int s3c24xx_iis_dev_probe(struct platform_device *pdev)
483 488
484 return 0; 489 return 0;
485err: 490err:
486 snd_soc_unregister_dai(&pdev->dev); 491 snd_soc_unregister_component(&pdev->dev);
487 return ret; 492 return ret;
488} 493}
489 494
490static int s3c24xx_iis_dev_remove(struct platform_device *pdev) 495static int s3c24xx_iis_dev_remove(struct platform_device *pdev)
491{ 496{
492 asoc_dma_platform_unregister(&pdev->dev); 497 asoc_dma_platform_unregister(&pdev->dev);
493 snd_soc_unregister_dai(&pdev->dev); 498 snd_soc_unregister_component(&pdev->dev);
494 return 0; 499 return 0;
495} 500}
496 501
diff --git a/sound/soc/samsung/s3c24xx_uda134x.c b/sound/soc/samsung/s3c24xx_uda134x.c
index 333e1b7f06c7..1b7b52b0af97 100644
--- a/sound/soc/samsung/s3c24xx_uda134x.c
+++ b/sound/soc/samsung/s3c24xx_uda134x.c
@@ -18,7 +18,7 @@
18#include <sound/soc.h> 18#include <sound/soc.h>
19#include <sound/s3c24xx_uda134x.h> 19#include <sound/s3c24xx_uda134x.h>
20 20
21#include <plat/regs-iis.h> 21#include "regs-iis.h"
22 22
23#include "s3c24xx-i2s.h" 23#include "s3c24xx-i2s.h"
24 24
diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c
index 5008e5bd6ed8..2e5ebb2f1982 100644
--- a/sound/soc/samsung/spdif.c
+++ b/sound/soc/samsung/spdif.c
@@ -357,6 +357,10 @@ static struct snd_soc_dai_driver samsung_spdif_dai = {
357 .resume = spdif_resume, 357 .resume = spdif_resume,
358}; 358};
359 359
360static const struct snd_soc_component_driver samsung_spdif_component = {
361 .name = "samsung-spdif",
362};
363
360static int spdif_probe(struct platform_device *pdev) 364static int spdif_probe(struct platform_device *pdev)
361{ 365{
362 struct s3c_audio_pdata *spdif_pdata; 366 struct s3c_audio_pdata *spdif_pdata;
@@ -424,7 +428,8 @@ static int spdif_probe(struct platform_device *pdev)
424 428
425 dev_set_drvdata(&pdev->dev, spdif); 429 dev_set_drvdata(&pdev->dev, spdif);
426 430
427 ret = snd_soc_register_dai(&pdev->dev, &samsung_spdif_dai); 431 ret = snd_soc_register_component(&pdev->dev, &samsung_spdif_component,
432 &samsung_spdif_dai, 1);
428 if (ret != 0) { 433 if (ret != 0) {
429 dev_err(&pdev->dev, "fail to register dai\n"); 434 dev_err(&pdev->dev, "fail to register dai\n");
430 goto err4; 435 goto err4;
@@ -445,7 +450,7 @@ static int spdif_probe(struct platform_device *pdev)
445 450
446 return 0; 451 return 0;
447err5: 452err5:
448 snd_soc_unregister_dai(&pdev->dev); 453 snd_soc_unregister_component(&pdev->dev);
449err4: 454err4:
450 iounmap(spdif->regs); 455 iounmap(spdif->regs);
451err3: 456err3:
@@ -466,7 +471,7 @@ static int spdif_remove(struct platform_device *pdev)
466 struct resource *mem_res; 471 struct resource *mem_res;
467 472
468 asoc_dma_platform_unregister(&pdev->dev); 473 asoc_dma_platform_unregister(&pdev->dev);
469 snd_soc_unregister_dai(&pdev->dev); 474 snd_soc_unregister_component(&pdev->dev);
470 475
471 iounmap(spdif->regs); 476 iounmap(spdif->regs);
472 477
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index c724026a246f..f830c41f97dd 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -296,7 +296,6 @@ struct fsi_core {
296 296
297struct fsi_master { 297struct fsi_master {
298 void __iomem *base; 298 void __iomem *base;
299 int irq;
300 struct fsi_priv fsia; 299 struct fsi_priv fsia;
301 struct fsi_priv fsib; 300 struct fsi_priv fsib;
302 const struct fsi_core *core; 301 const struct fsi_core *core;
@@ -1886,6 +1885,10 @@ static struct snd_soc_platform_driver fsi_soc_platform = {
1886 .pcm_free = fsi_pcm_free, 1885 .pcm_free = fsi_pcm_free,
1887}; 1886};
1888 1887
1888static const struct snd_soc_component_driver fsi_soc_component = {
1889 .name = "fsi",
1890};
1891
1889/* 1892/*
1890 * platform function 1893 * platform function
1891 */ 1894 */
@@ -2002,7 +2005,6 @@ static int fsi_probe(struct platform_device *pdev)
2002 } 2005 }
2003 2006
2004 /* master setting */ 2007 /* master setting */
2005 master->irq = irq;
2006 master->core = core; 2008 master->core = core;
2007 spin_lock_init(&master->lock); 2009 spin_lock_init(&master->lock);
2008 2010
@@ -2046,10 +2048,10 @@ static int fsi_probe(struct platform_device *pdev)
2046 goto exit_fsib; 2048 goto exit_fsib;
2047 } 2049 }
2048 2050
2049 ret = snd_soc_register_dais(&pdev->dev, fsi_soc_dai, 2051 ret = snd_soc_register_component(&pdev->dev, &fsi_soc_component,
2050 ARRAY_SIZE(fsi_soc_dai)); 2052 fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai));
2051 if (ret < 0) { 2053 if (ret < 0) {
2052 dev_err(&pdev->dev, "cannot snd dai register\n"); 2054 dev_err(&pdev->dev, "cannot snd component register\n");
2053 goto exit_snd_soc; 2055 goto exit_snd_soc;
2054 } 2056 }
2055 2057
@@ -2074,7 +2076,7 @@ static int fsi_remove(struct platform_device *pdev)
2074 2076
2075 pm_runtime_disable(&pdev->dev); 2077 pm_runtime_disable(&pdev->dev);
2076 2078
2077 snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai)); 2079 snd_soc_unregister_component(&pdev->dev);
2078 snd_soc_unregister_platform(&pdev->dev); 2080 snd_soc_unregister_platform(&pdev->dev);
2079 2081
2080 fsi_stream_remove(&master->fsia); 2082 fsi_stream_remove(&master->fsia);
diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c
index 4cc2d64ef476..af19f77b7bf0 100644
--- a/sound/soc/sh/hac.c
+++ b/sound/soc/sh/hac.c
@@ -310,15 +310,19 @@ static struct snd_soc_dai_driver sh4_hac_dai[] = {
310#endif 310#endif
311}; 311};
312 312
313static const struct snd_soc_component_driver sh4_hac_component = {
314 .name = "sh4-hac",
315};
316
313static int hac_soc_platform_probe(struct platform_device *pdev) 317static int hac_soc_platform_probe(struct platform_device *pdev)
314{ 318{
315 return snd_soc_register_dais(&pdev->dev, sh4_hac_dai, 319 return snd_soc_register_component(&pdev->dev, &sh4_hac_component,
316 ARRAY_SIZE(sh4_hac_dai)); 320 sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai));
317} 321}
318 322
319static int hac_soc_platform_remove(struct platform_device *pdev) 323static int hac_soc_platform_remove(struct platform_device *pdev)
320{ 324{
321 snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(sh4_hac_dai)); 325 snd_soc_unregister_component(&pdev->dev);
322 return 0; 326 return 0;
323} 327}
324 328
diff --git a/sound/soc/sh/migor.c b/sound/soc/sh/migor.c
index 8526e1edaf45..5014a884afee 100644
--- a/sound/soc/sh/migor.c
+++ b/sound/soc/sh/migor.c
@@ -153,7 +153,7 @@ static int migor_dai_init(struct snd_soc_pcm_runtime *rtd)
153static struct snd_soc_dai_link migor_dai = { 153static struct snd_soc_dai_link migor_dai = {
154 .name = "wm8978", 154 .name = "wm8978",
155 .stream_name = "WM8978", 155 .stream_name = "WM8978",
156 .cpu_dai_name = "siu-i2s-dai", 156 .cpu_dai_name = "siu-pcm-audio",
157 .codec_dai_name = "wm8978-hifi", 157 .codec_dai_name = "wm8978-hifi",
158 .platform_name = "siu-pcm-audio", 158 .platform_name = "siu-pcm-audio",
159 .codec_name = "wm8978.0-001a", 159 .codec_name = "wm8978.0-001a",
diff --git a/sound/soc/sh/siu_dai.c b/sound/soc/sh/siu_dai.c
index 34facdc9e4ac..9dc24ffa892a 100644
--- a/sound/soc/sh/siu_dai.c
+++ b/sound/soc/sh/siu_dai.c
@@ -726,6 +726,10 @@ static struct snd_soc_dai_driver siu_i2s_dai = {
726 .ops = &siu_dai_ops, 726 .ops = &siu_dai_ops,
727}; 727};
728 728
729static const struct snd_soc_component_driver siu_i2s_component = {
730 .name = "siu-i2s",
731};
732
729static int siu_probe(struct platform_device *pdev) 733static int siu_probe(struct platform_device *pdev)
730{ 734{
731 const struct firmware *fw_entry; 735 const struct firmware *fw_entry;
@@ -783,7 +787,8 @@ static int siu_probe(struct platform_device *pdev)
783 dev_set_drvdata(&pdev->dev, info); 787 dev_set_drvdata(&pdev->dev, info);
784 788
785 /* register using ARRAY version so we can keep dai name */ 789 /* register using ARRAY version so we can keep dai name */
786 ret = snd_soc_register_dais(&pdev->dev, &siu_i2s_dai, 1); 790 ret = snd_soc_register_component(&pdev->dev, &siu_i2s_component,
791 &siu_i2s_dai, 1);
787 if (ret < 0) 792 if (ret < 0)
788 goto edaiinit; 793 goto edaiinit;
789 794
@@ -796,7 +801,7 @@ static int siu_probe(struct platform_device *pdev)
796 return ret; 801 return ret;
797 802
798esocregp: 803esocregp:
799 snd_soc_unregister_dai(&pdev->dev); 804 snd_soc_unregister_component(&pdev->dev);
800edaiinit: 805edaiinit:
801 iounmap(info->reg); 806 iounmap(info->reg);
802emapreg: 807emapreg:
@@ -823,7 +828,7 @@ static int siu_remove(struct platform_device *pdev)
823 pm_runtime_disable(&pdev->dev); 828 pm_runtime_disable(&pdev->dev);
824 829
825 snd_soc_unregister_platform(&pdev->dev); 830 snd_soc_unregister_platform(&pdev->dev);
826 snd_soc_unregister_dai(&pdev->dev); 831 snd_soc_unregister_component(&pdev->dev);
827 832
828 iounmap(info->reg); 833 iounmap(info->reg);
829 iounmap(info->yram); 834 iounmap(info->yram);
diff --git a/sound/soc/sh/ssi.c b/sound/soc/sh/ssi.c
index c8e73a703934..e889405ebd38 100644
--- a/sound/soc/sh/ssi.c
+++ b/sound/soc/sh/ssi.c
@@ -379,15 +379,19 @@ static struct snd_soc_dai_driver sh4_ssi_dai[] = {
379#endif 379#endif
380}; 380};
381 381
382static const struct snd_soc_component_driver sh4_ssi_component = {
383 .name = "sh4-ssi",
384};
385
382static int sh4_soc_dai_probe(struct platform_device *pdev) 386static int sh4_soc_dai_probe(struct platform_device *pdev)
383{ 387{
384 return snd_soc_register_dais(&pdev->dev, sh4_ssi_dai, 388 return snd_soc_register_component(&pdev->dev, &sh4_ssi_component,
385 ARRAY_SIZE(sh4_ssi_dai)); 389 sh4_ssi_dai, ARRAY_SIZE(sh4_ssi_dai));
386} 390}
387 391
388static int sh4_soc_dai_remove(struct platform_device *pdev) 392static int sh4_soc_dai_remove(struct platform_device *pdev)
389{ 393{
390 snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(sh4_ssi_dai)); 394 snd_soc_unregister_component(&pdev->dev);
391 return 0; 395 return 0;
392} 396}
393 397
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index ed0bfb0ddb96..3853f7eb3f28 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -315,7 +315,7 @@ static int soc_compr_pointer(struct snd_compr_stream *cstream,
315} 315}
316 316
317static int soc_compr_copy(struct snd_compr_stream *cstream, 317static int soc_compr_copy(struct snd_compr_stream *cstream,
318 const char __user *buf, size_t count) 318 char __user *buf, size_t count)
319{ 319{
320 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 320 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
321 struct snd_soc_platform *platform = rtd->platform; 321 struct snd_soc_platform *platform = rtd->platform;
@@ -330,11 +330,38 @@ static int soc_compr_copy(struct snd_compr_stream *cstream,
330 return ret; 330 return ret;
331} 331}
332 332
333static int sst_compr_set_metadata(struct snd_compr_stream *cstream,
334 struct snd_compr_metadata *metadata)
335{
336 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
337 struct snd_soc_platform *platform = rtd->platform;
338 int ret = 0;
339
340 if (platform->driver->compr_ops && platform->driver->compr_ops->set_metadata)
341 ret = platform->driver->compr_ops->set_metadata(cstream, metadata);
342
343 return ret;
344}
345
346static int sst_compr_get_metadata(struct snd_compr_stream *cstream,
347 struct snd_compr_metadata *metadata)
348{
349 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
350 struct snd_soc_platform *platform = rtd->platform;
351 int ret = 0;
352
353 if (platform->driver->compr_ops && platform->driver->compr_ops->get_metadata)
354 ret = platform->driver->compr_ops->get_metadata(cstream, metadata);
355
356 return ret;
357}
333/* ASoC Compress operations */ 358/* ASoC Compress operations */
334static struct snd_compr_ops soc_compr_ops = { 359static struct snd_compr_ops soc_compr_ops = {
335 .open = soc_compr_open, 360 .open = soc_compr_open,
336 .free = soc_compr_free, 361 .free = soc_compr_free,
337 .set_params = soc_compr_set_params, 362 .set_params = soc_compr_set_params,
363 .set_metadata = sst_compr_set_metadata,
364 .get_metadata = sst_compr_get_metadata,
338 .get_params = soc_compr_get_params, 365 .get_params = soc_compr_get_params,
339 .trigger = soc_compr_trigger, 366 .trigger = soc_compr_trigger,
340 .pointer = soc_compr_pointer, 367 .pointer = soc_compr_pointer,
@@ -357,7 +384,14 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
357 /* check client and interface hw capabilities */ 384 /* check client and interface hw capabilities */
358 snprintf(new_name, sizeof(new_name), "%s %s-%d", 385 snprintf(new_name, sizeof(new_name), "%s %s-%d",
359 rtd->dai_link->stream_name, codec_dai->name, num); 386 rtd->dai_link->stream_name, codec_dai->name, num);
360 direction = SND_COMPRESS_PLAYBACK; 387
388 if (codec_dai->driver->playback.channels_min)
389 direction = SND_COMPRESS_PLAYBACK;
390 else if (codec_dai->driver->capture.channels_min)
391 direction = SND_COMPRESS_CAPTURE;
392 else
393 return -EINVAL;
394
361 compr = kzalloc(sizeof(*compr), GFP_KERNEL); 395 compr = kzalloc(sizeof(*compr), GFP_KERNEL);
362 if (compr == NULL) { 396 if (compr == NULL) {
363 snd_printk(KERN_ERR "Cannot allocate compr\n"); 397 snd_printk(KERN_ERR "Cannot allocate compr\n");
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index ff4b45a5d796..d56bbea6e75e 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -58,6 +58,7 @@ static DEFINE_MUTEX(client_mutex);
58static LIST_HEAD(dai_list); 58static LIST_HEAD(dai_list);
59static LIST_HEAD(platform_list); 59static LIST_HEAD(platform_list);
60static LIST_HEAD(codec_list); 60static LIST_HEAD(codec_list);
61static LIST_HEAD(component_list);
61 62
62/* 63/*
63 * This is a timeout to do a DAPM powerdown after a stream is closed(). 64 * This is a timeout to do a DAPM powerdown after a stream is closed().
@@ -3740,7 +3741,7 @@ static inline char *fmt_multiple_name(struct device *dev,
3740 * 3741 *
3741 * @dai: DAI to register 3742 * @dai: DAI to register
3742 */ 3743 */
3743int snd_soc_register_dai(struct device *dev, 3744static int snd_soc_register_dai(struct device *dev,
3744 struct snd_soc_dai_driver *dai_drv) 3745 struct snd_soc_dai_driver *dai_drv)
3745{ 3746{
3746 struct snd_soc_codec *codec; 3747 struct snd_soc_codec *codec;
@@ -3787,14 +3788,13 @@ int snd_soc_register_dai(struct device *dev,
3787 3788
3788 return 0; 3789 return 0;
3789} 3790}
3790EXPORT_SYMBOL_GPL(snd_soc_register_dai);
3791 3791
3792/** 3792/**
3793 * snd_soc_unregister_dai - Unregister a DAI from the ASoC core 3793 * snd_soc_unregister_dai - Unregister a DAI from the ASoC core
3794 * 3794 *
3795 * @dai: DAI to unregister 3795 * @dai: DAI to unregister
3796 */ 3796 */
3797void snd_soc_unregister_dai(struct device *dev) 3797static void snd_soc_unregister_dai(struct device *dev)
3798{ 3798{
3799 struct snd_soc_dai *dai; 3799 struct snd_soc_dai *dai;
3800 3800
@@ -3813,7 +3813,6 @@ found:
3813 kfree(dai->name); 3813 kfree(dai->name);
3814 kfree(dai); 3814 kfree(dai);
3815} 3815}
3816EXPORT_SYMBOL_GPL(snd_soc_unregister_dai);
3817 3816
3818/** 3817/**
3819 * snd_soc_register_dais - Register multiple DAIs with the ASoC core 3818 * snd_soc_register_dais - Register multiple DAIs with the ASoC core
@@ -3821,7 +3820,7 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_dai);
3821 * @dai: Array of DAIs to register 3820 * @dai: Array of DAIs to register
3822 * @count: Number of DAIs 3821 * @count: Number of DAIs
3823 */ 3822 */
3824int snd_soc_register_dais(struct device *dev, 3823static int snd_soc_register_dais(struct device *dev,
3825 struct snd_soc_dai_driver *dai_drv, size_t count) 3824 struct snd_soc_dai_driver *dai_drv, size_t count)
3826{ 3825{
3827 struct snd_soc_codec *codec; 3826 struct snd_soc_codec *codec;
@@ -3885,7 +3884,6 @@ err:
3885 3884
3886 return ret; 3885 return ret;
3887} 3886}
3888EXPORT_SYMBOL_GPL(snd_soc_register_dais);
3889 3887
3890/** 3888/**
3891 * snd_soc_unregister_dais - Unregister multiple DAIs from the ASoC core 3889 * snd_soc_unregister_dais - Unregister multiple DAIs from the ASoC core
@@ -3893,31 +3891,23 @@ EXPORT_SYMBOL_GPL(snd_soc_register_dais);
3893 * @dai: Array of DAIs to unregister 3891 * @dai: Array of DAIs to unregister
3894 * @count: Number of DAIs 3892 * @count: Number of DAIs
3895 */ 3893 */
3896void snd_soc_unregister_dais(struct device *dev, size_t count) 3894static void snd_soc_unregister_dais(struct device *dev, size_t count)
3897{ 3895{
3898 int i; 3896 int i;
3899 3897
3900 for (i = 0; i < count; i++) 3898 for (i = 0; i < count; i++)
3901 snd_soc_unregister_dai(dev); 3899 snd_soc_unregister_dai(dev);
3902} 3900}
3903EXPORT_SYMBOL_GPL(snd_soc_unregister_dais);
3904 3901
3905/** 3902/**
3906 * snd_soc_register_platform - Register a platform with the ASoC core 3903 * snd_soc_add_platform - Add a platform to the ASoC core
3907 * 3904 * @dev: The parent device for the platform
3908 * @platform: platform to register 3905 * @platform: The platform to add
3906 * @platform_driver: The driver for the platform
3909 */ 3907 */
3910int snd_soc_register_platform(struct device *dev, 3908int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform,
3911 struct snd_soc_platform_driver *platform_drv) 3909 const struct snd_soc_platform_driver *platform_drv)
3912{ 3910{
3913 struct snd_soc_platform *platform;
3914
3915 dev_dbg(dev, "ASoC: platform register %s\n", dev_name(dev));
3916
3917 platform = kzalloc(sizeof(struct snd_soc_platform), GFP_KERNEL);
3918 if (platform == NULL)
3919 return -ENOMEM;
3920
3921 /* create platform component name */ 3911 /* create platform component name */
3922 platform->name = fmt_single_name(dev, &platform->id); 3912 platform->name = fmt_single_name(dev, &platform->id);
3923 if (platform->name == NULL) { 3913 if (platform->name == NULL) {
@@ -3940,30 +3930,76 @@ int snd_soc_register_platform(struct device *dev,
3940 3930
3941 return 0; 3931 return 0;
3942} 3932}
3943EXPORT_SYMBOL_GPL(snd_soc_register_platform); 3933EXPORT_SYMBOL_GPL(snd_soc_add_platform);
3944 3934
3945/** 3935/**
3946 * snd_soc_unregister_platform - Unregister a platform from the ASoC core 3936 * snd_soc_register_platform - Register a platform with the ASoC core
3947 * 3937 *
3948 * @platform: platform to unregister 3938 * @platform: platform to register
3949 */ 3939 */
3950void snd_soc_unregister_platform(struct device *dev) 3940int snd_soc_register_platform(struct device *dev,
3941 const struct snd_soc_platform_driver *platform_drv)
3951{ 3942{
3952 struct snd_soc_platform *platform; 3943 struct snd_soc_platform *platform;
3944 int ret;
3953 3945
3954 list_for_each_entry(platform, &platform_list, list) { 3946 dev_dbg(dev, "ASoC: platform register %s\n", dev_name(dev));
3955 if (dev == platform->dev)
3956 goto found;
3957 }
3958 return;
3959 3947
3960found: 3948 platform = kzalloc(sizeof(struct snd_soc_platform), GFP_KERNEL);
3949 if (platform == NULL)
3950 return -ENOMEM;
3951
3952 ret = snd_soc_add_platform(dev, platform, platform_drv);
3953 if (ret)
3954 kfree(platform);
3955
3956 return ret;
3957}
3958EXPORT_SYMBOL_GPL(snd_soc_register_platform);
3959
3960/**
3961 * snd_soc_remove_platform - Remove a platform from the ASoC core
3962 * @platform: the platform to remove
3963 */
3964void snd_soc_remove_platform(struct snd_soc_platform *platform)
3965{
3961 mutex_lock(&client_mutex); 3966 mutex_lock(&client_mutex);
3962 list_del(&platform->list); 3967 list_del(&platform->list);
3963 mutex_unlock(&client_mutex); 3968 mutex_unlock(&client_mutex);
3964 3969
3965 dev_dbg(dev, "ASoC: Unregistered platform '%s'\n", platform->name); 3970 dev_dbg(platform->dev, "ASoC: Unregistered platform '%s'\n",
3971 platform->name);
3966 kfree(platform->name); 3972 kfree(platform->name);
3973}
3974EXPORT_SYMBOL_GPL(snd_soc_remove_platform);
3975
3976struct snd_soc_platform *snd_soc_lookup_platform(struct device *dev)
3977{
3978 struct snd_soc_platform *platform;
3979
3980 list_for_each_entry(platform, &platform_list, list) {
3981 if (dev == platform->dev)
3982 return platform;
3983 }
3984
3985 return NULL;
3986}
3987EXPORT_SYMBOL_GPL(snd_soc_lookup_platform);
3988
3989/**
3990 * snd_soc_unregister_platform - Unregister a platform from the ASoC core
3991 *
3992 * @platform: platform to unregister
3993 */
3994void snd_soc_unregister_platform(struct device *dev)
3995{
3996 struct snd_soc_platform *platform;
3997
3998 platform = snd_soc_lookup_platform(dev);
3999 if (!platform)
4000 return;
4001
4002 snd_soc_remove_platform(platform);
3967 kfree(platform); 4003 kfree(platform);
3968} 4004}
3969EXPORT_SYMBOL_GPL(snd_soc_unregister_platform); 4005EXPORT_SYMBOL_GPL(snd_soc_unregister_platform);
@@ -4024,8 +4060,8 @@ int snd_soc_register_codec(struct device *dev,
4024 /* create CODEC component name */ 4060 /* create CODEC component name */
4025 codec->name = fmt_single_name(dev, &codec->id); 4061 codec->name = fmt_single_name(dev, &codec->id);
4026 if (codec->name == NULL) { 4062 if (codec->name == NULL) {
4027 kfree(codec); 4063 ret = -ENOMEM;
4028 return -ENOMEM; 4064 goto fail_codec;
4029 } 4065 }
4030 4066
4031 if (codec_drv->compress_type) 4067 if (codec_drv->compress_type)
@@ -4064,7 +4100,7 @@ int snd_soc_register_codec(struct device *dev,
4064 reg_size, GFP_KERNEL); 4100 reg_size, GFP_KERNEL);
4065 if (!codec->reg_def_copy) { 4101 if (!codec->reg_def_copy) {
4066 ret = -ENOMEM; 4102 ret = -ENOMEM;
4067 goto fail; 4103 goto fail_codec_name;
4068 } 4104 }
4069 } 4105 }
4070 } 4106 }
@@ -4088,18 +4124,22 @@ int snd_soc_register_codec(struct device *dev,
4088 mutex_unlock(&client_mutex); 4124 mutex_unlock(&client_mutex);
4089 4125
4090 /* register any DAIs */ 4126 /* register any DAIs */
4091 if (num_dai) { 4127 ret = snd_soc_register_dais(dev, dai_drv, num_dai);
4092 ret = snd_soc_register_dais(dev, dai_drv, num_dai); 4128 if (ret < 0) {
4093 if (ret < 0) 4129 dev_err(codec->dev, "ASoC: Failed to regster DAIs: %d\n", ret);
4094 dev_err(codec->dev, "ASoC: Failed to regster" 4130 goto fail_codec_name;
4095 " DAIs: %d\n", ret);
4096 } 4131 }
4097 4132
4098 dev_dbg(codec->dev, "ASoC: Registered codec '%s'\n", codec->name); 4133 dev_dbg(codec->dev, "ASoC: Registered codec '%s'\n", codec->name);
4099 return 0; 4134 return 0;
4100 4135
4101fail: 4136fail_codec_name:
4137 mutex_lock(&client_mutex);
4138 list_del(&codec->list);
4139 mutex_unlock(&client_mutex);
4140
4102 kfree(codec->name); 4141 kfree(codec->name);
4142fail_codec:
4103 kfree(codec); 4143 kfree(codec);
4104 return ret; 4144 return ret;
4105} 4145}
@@ -4113,7 +4153,6 @@ EXPORT_SYMBOL_GPL(snd_soc_register_codec);
4113void snd_soc_unregister_codec(struct device *dev) 4153void snd_soc_unregister_codec(struct device *dev)
4114{ 4154{
4115 struct snd_soc_codec *codec; 4155 struct snd_soc_codec *codec;
4116 int i;
4117 4156
4118 list_for_each_entry(codec, &codec_list, list) { 4157 list_for_each_entry(codec, &codec_list, list) {
4119 if (dev == codec->dev) 4158 if (dev == codec->dev)
@@ -4122,9 +4161,7 @@ void snd_soc_unregister_codec(struct device *dev)
4122 return; 4161 return;
4123 4162
4124found: 4163found:
4125 if (codec->num_dai) 4164 snd_soc_unregister_dais(dev, codec->num_dai);
4126 for (i = 0; i < codec->num_dai; i++)
4127 snd_soc_unregister_dai(dev);
4128 4165
4129 mutex_lock(&client_mutex); 4166 mutex_lock(&client_mutex);
4130 list_del(&codec->list); 4167 list_del(&codec->list);
@@ -4139,6 +4176,92 @@ found:
4139} 4176}
4140EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); 4177EXPORT_SYMBOL_GPL(snd_soc_unregister_codec);
4141 4178
4179
4180/**
4181 * snd_soc_register_component - Register a component with the ASoC core
4182 *
4183 */
4184int snd_soc_register_component(struct device *dev,
4185 const struct snd_soc_component_driver *cmpnt_drv,
4186 struct snd_soc_dai_driver *dai_drv,
4187 int num_dai)
4188{
4189 struct snd_soc_component *cmpnt;
4190 int ret;
4191
4192 dev_dbg(dev, "component register %s\n", dev_name(dev));
4193
4194 cmpnt = devm_kzalloc(dev, sizeof(*cmpnt), GFP_KERNEL);
4195 if (!cmpnt) {
4196 dev_err(dev, "ASoC: Failed to allocate memory\n");
4197 return -ENOMEM;
4198 }
4199
4200 cmpnt->name = fmt_single_name(dev, &cmpnt->id);
4201 if (!cmpnt->name) {
4202 dev_err(dev, "ASoC: Failed to simplifying name\n");
4203 return -ENOMEM;
4204 }
4205
4206 cmpnt->dev = dev;
4207 cmpnt->driver = cmpnt_drv;
4208 cmpnt->num_dai = num_dai;
4209
4210 /*
4211 * snd_soc_register_dai() uses fmt_single_name(), and
4212 * snd_soc_register_dais() uses fmt_multiple_name()
4213 * for dai->name which is used for name based matching
4214 */
4215 if (1 == num_dai)
4216 ret = snd_soc_register_dai(dev, dai_drv);
4217 else
4218 ret = snd_soc_register_dais(dev, dai_drv, num_dai);
4219 if (ret < 0) {
4220 dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret);
4221 goto error_component_name;
4222 }
4223
4224 mutex_lock(&client_mutex);
4225 list_add(&cmpnt->list, &component_list);
4226 mutex_unlock(&client_mutex);
4227
4228 dev_dbg(cmpnt->dev, "ASoC: Registered component '%s'\n", cmpnt->name);
4229
4230 return ret;
4231
4232error_component_name:
4233 kfree(cmpnt->name);
4234
4235 return ret;
4236}
4237EXPORT_SYMBOL_GPL(snd_soc_register_component);
4238
4239/**
4240 * snd_soc_unregister_component - Unregister a component from the ASoC core
4241 *
4242 */
4243void snd_soc_unregister_component(struct device *dev)
4244{
4245 struct snd_soc_component *cmpnt;
4246
4247 list_for_each_entry(cmpnt, &component_list, list) {
4248 if (dev == cmpnt->dev)
4249 goto found;
4250 }
4251 return;
4252
4253found:
4254 snd_soc_unregister_dais(dev, cmpnt->num_dai);
4255
4256 mutex_lock(&client_mutex);
4257 list_del(&cmpnt->list);
4258 mutex_unlock(&client_mutex);
4259
4260 dev_dbg(dev, "ASoC: Unregistered component '%s'\n", cmpnt->name);
4261 kfree(cmpnt->name);
4262}
4263EXPORT_SYMBOL_GPL(snd_soc_unregister_component);
4264
4142/* Retrieve a card's name from device tree */ 4265/* Retrieve a card's name from device tree */
4143int snd_soc_of_parse_card_name(struct snd_soc_card *card, 4266int snd_soc_of_parse_card_name(struct snd_soc_card *card,
4144 const char *propname) 4267 const char *propname)
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index d6d9ba2e6916..21779a6a781a 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -504,17 +504,27 @@ static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm,
504 return 0; 504 return 0;
505} 505}
506 506
507/* create new dapm mixer control */ 507/*
508static int dapm_new_mixer(struct snd_soc_dapm_widget *w) 508 * Determine if a kcontrol is shared. If it is, look it up. If it isn't,
509 * create it. Either way, add the widget into the control's widget list
510 */
511static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
512 int kci, struct snd_soc_dapm_path *path)
509{ 513{
510 struct snd_soc_dapm_context *dapm = w->dapm; 514 struct snd_soc_dapm_context *dapm = w->dapm;
511 int i, ret = 0;
512 size_t name_len, prefix_len;
513 struct snd_soc_dapm_path *path;
514 struct snd_card *card = dapm->card->snd_card; 515 struct snd_card *card = dapm->card->snd_card;
515 const char *prefix; 516 const char *prefix;
517 size_t prefix_len;
518 int shared;
519 struct snd_kcontrol *kcontrol;
516 struct snd_soc_dapm_widget_list *wlist; 520 struct snd_soc_dapm_widget_list *wlist;
521 int wlistentries;
517 size_t wlistsize; 522 size_t wlistsize;
523 bool wname_in_long_name, kcname_in_long_name;
524 size_t name_len;
525 char *long_name;
526 const char *name;
527 int ret;
518 528
519 if (dapm->codec) 529 if (dapm->codec)
520 prefix = dapm->codec->name_prefix; 530 prefix = dapm->codec->name_prefix;
@@ -526,103 +536,141 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
526 else 536 else
527 prefix_len = 0; 537 prefix_len = 0;
528 538
529 /* add kcontrol */ 539 shared = dapm_is_shared_kcontrol(dapm, w, &w->kcontrol_news[kci],
530 for (i = 0; i < w->num_kcontrols; i++) { 540 &kcontrol);
531 541
532 /* match name */ 542 if (kcontrol) {
533 list_for_each_entry(path, &w->sources, list_sink) { 543 wlist = kcontrol->private_data;
544 wlistentries = wlist->num_widgets + 1;
545 } else {
546 wlist = NULL;
547 wlistentries = 1;
548 }
534 549
535 /* mixer/mux paths name must match control name */ 550 wlistsize = sizeof(struct snd_soc_dapm_widget_list) +
536 if (path->name != (char *)w->kcontrol_news[i].name) 551 wlistentries * sizeof(struct snd_soc_dapm_widget *);
537 continue; 552 wlist = krealloc(wlist, wlistsize, GFP_KERNEL);
553 if (wlist == NULL) {
554 dev_err(dapm->dev, "ASoC: can't allocate widget list for %s\n",
555 w->name);
556 return -ENOMEM;
557 }
558 wlist->num_widgets = wlistentries;
559 wlist->widgets[wlistentries - 1] = w;
538 560
539 if (w->kcontrols[i]) { 561 if (!kcontrol) {
540 path->kcontrol = w->kcontrols[i]; 562 if (shared) {
541 continue; 563 wname_in_long_name = false;
564 kcname_in_long_name = true;
565 } else {
566 switch (w->id) {
567 case snd_soc_dapm_switch:
568 case snd_soc_dapm_mixer:
569 wname_in_long_name = true;
570 kcname_in_long_name = true;
571 break;
572 case snd_soc_dapm_mixer_named_ctl:
573 wname_in_long_name = false;
574 kcname_in_long_name = true;
575 break;
576 case snd_soc_dapm_mux:
577 case snd_soc_dapm_virt_mux:
578 case snd_soc_dapm_value_mux:
579 wname_in_long_name = true;
580 kcname_in_long_name = false;
581 break;
582 default:
583 kfree(wlist);
584 return -EINVAL;
542 } 585 }
586 }
587
588 if (wname_in_long_name && kcname_in_long_name) {
589 name_len = strlen(w->name) - prefix_len + 1 +
590 strlen(w->kcontrol_news[kci].name) + 1;
543 591
544 wlistsize = sizeof(struct snd_soc_dapm_widget_list) + 592 long_name = kmalloc(name_len, GFP_KERNEL);
545 sizeof(struct snd_soc_dapm_widget *), 593 if (long_name == NULL) {
546 wlist = kzalloc(wlistsize, GFP_KERNEL); 594 kfree(wlist);
547 if (wlist == NULL) {
548 dev_err(dapm->dev,
549 "ASoC: can't allocate widget list for %s\n",
550 w->name);
551 return -ENOMEM; 595 return -ENOMEM;
552 } 596 }
553 wlist->num_widgets = 1; 597
554 wlist->widgets[0] = w; 598 /*
555 599 * The control will get a prefix from the control
556 /* add dapm control with long name. 600 * creation process but we're also using the same
557 * for dapm_mixer this is the concatenation of the 601 * prefix for widgets so cut the prefix off the
558 * mixer and kcontrol name. 602 * front of the widget name.
559 * for dapm_mixer_named_ctl this is simply the
560 * kcontrol name.
561 */ 603 */
562 name_len = strlen(w->kcontrol_news[i].name) + 1; 604 snprintf(long_name, name_len, "%s %s",
563 if (w->id != snd_soc_dapm_mixer_named_ctl) 605 w->name + prefix_len,
564 name_len += 1 + strlen(w->name); 606 w->kcontrol_news[kci].name);
607 long_name[name_len - 1] = '\0';
608
609 name = long_name;
610 } else if (wname_in_long_name) {
611 long_name = NULL;
612 name = w->name + prefix_len;
613 } else {
614 long_name = NULL;
615 name = w->kcontrol_news[kci].name;
616 }
565 617
566 path->long_name = kmalloc(name_len, GFP_KERNEL); 618 kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], wlist, name,
619 prefix);
620 ret = snd_ctl_add(card, kcontrol);
621 if (ret < 0) {
622 dev_err(dapm->dev,
623 "ASoC: failed to add widget %s dapm kcontrol %s: %d\n",
624 w->name, name, ret);
625 kfree(wlist);
626 kfree(long_name);
627 return ret;
628 }
567 629
568 if (path->long_name == NULL) { 630 path->long_name = long_name;
569 kfree(wlist); 631 }
570 return -ENOMEM;
571 }
572 632
573 switch (w->id) { 633 kcontrol->private_data = wlist;
574 default: 634 w->kcontrols[kci] = kcontrol;
575 /* The control will get a prefix from 635 path->kcontrol = kcontrol;
576 * the control creation process but
577 * we're also using the same prefix
578 * for widgets so cut the prefix off
579 * the front of the widget name.
580 */
581 snprintf((char *)path->long_name, name_len,
582 "%s %s", w->name + prefix_len,
583 w->kcontrol_news[i].name);
584 break;
585 case snd_soc_dapm_mixer_named_ctl:
586 snprintf((char *)path->long_name, name_len,
587 "%s", w->kcontrol_news[i].name);
588 break;
589 }
590 636
591 ((char *)path->long_name)[name_len - 1] = '\0'; 637 return 0;
638}
592 639
593 path->kcontrol = snd_soc_cnew(&w->kcontrol_news[i], 640/* create new dapm mixer control */
594 wlist, path->long_name, 641static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
595 prefix); 642{
596 ret = snd_ctl_add(card, path->kcontrol); 643 int i, ret;
597 if (ret < 0) { 644 struct snd_soc_dapm_path *path;
598 dev_err(dapm->dev, "ASoC: failed to add widget" 645
599 " %s dapm kcontrol %s: %d\n", 646 /* add kcontrol */
600 w->name, path->long_name, ret); 647 for (i = 0; i < w->num_kcontrols; i++) {
601 kfree(wlist); 648 /* match name */
602 kfree(path->long_name); 649 list_for_each_entry(path, &w->sources, list_sink) {
603 path->long_name = NULL; 650 /* mixer/mux paths name must match control name */
604 return ret; 651 if (path->name != (char *)w->kcontrol_news[i].name)
652 continue;
653
654 if (w->kcontrols[i]) {
655 path->kcontrol = w->kcontrols[i];
656 continue;
605 } 657 }
606 w->kcontrols[i] = path->kcontrol; 658
659 ret = dapm_create_or_share_mixmux_kcontrol(w, i, path);
660 if (ret < 0)
661 return ret;
607 } 662 }
608 } 663 }
609 return ret; 664
665 return 0;
610} 666}
611 667
612/* create new dapm mux control */ 668/* create new dapm mux control */
613static int dapm_new_mux(struct snd_soc_dapm_widget *w) 669static int dapm_new_mux(struct snd_soc_dapm_widget *w)
614{ 670{
615 struct snd_soc_dapm_context *dapm = w->dapm; 671 struct snd_soc_dapm_context *dapm = w->dapm;
616 struct snd_soc_dapm_path *path = NULL; 672 struct snd_soc_dapm_path *path;
617 struct snd_kcontrol *kcontrol;
618 struct snd_card *card = dapm->card->snd_card;
619 const char *prefix;
620 size_t prefix_len;
621 int ret; 673 int ret;
622 struct snd_soc_dapm_widget_list *wlist;
623 int shared, wlistentries;
624 size_t wlistsize;
625 const char *name;
626 674
627 if (w->num_kcontrols != 1) { 675 if (w->num_kcontrols != 1) {
628 dev_err(dapm->dev, 676 dev_err(dapm->dev,
@@ -631,65 +679,19 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
631 return -EINVAL; 679 return -EINVAL;
632 } 680 }
633 681
634 shared = dapm_is_shared_kcontrol(dapm, w, &w->kcontrol_news[0], 682 path = list_first_entry(&w->sources, struct snd_soc_dapm_path,
635 &kcontrol); 683 list_sink);
636 if (kcontrol) { 684 if (!path) {
637 wlist = kcontrol->private_data; 685 dev_err(dapm->dev, "ASoC: mux %s has no paths\n", w->name);
638 wlistentries = wlist->num_widgets + 1; 686 return -EINVAL;
639 } else {
640 wlist = NULL;
641 wlistentries = 1;
642 }
643 wlistsize = sizeof(struct snd_soc_dapm_widget_list) +
644 wlistentries * sizeof(struct snd_soc_dapm_widget *),
645 wlist = krealloc(wlist, wlistsize, GFP_KERNEL);
646 if (wlist == NULL) {
647 dev_err(dapm->dev,
648 "ASoC: can't allocate widget list for %s\n", w->name);
649 return -ENOMEM;
650 }
651 wlist->num_widgets = wlistentries;
652 wlist->widgets[wlistentries - 1] = w;
653
654 if (!kcontrol) {
655 if (dapm->codec)
656 prefix = dapm->codec->name_prefix;
657 else
658 prefix = NULL;
659
660 if (shared) {
661 name = w->kcontrol_news[0].name;
662 prefix_len = 0;
663 } else {
664 name = w->name;
665 if (prefix)
666 prefix_len = strlen(prefix) + 1;
667 else
668 prefix_len = 0;
669 }
670
671 /*
672 * The control will get a prefix from the control creation
673 * process but we're also using the same prefix for widgets so
674 * cut the prefix off the front of the widget name.
675 */
676 kcontrol = snd_soc_cnew(&w->kcontrol_news[0], wlist,
677 name + prefix_len, prefix);
678 ret = snd_ctl_add(card, kcontrol);
679 if (ret < 0) {
680 dev_err(dapm->dev, "ASoC: failed to add kcontrol %s: %d\n",
681 w->name, ret);
682 kfree(wlist);
683 return ret;
684 }
685 } 687 }
686 688
687 kcontrol->private_data = wlist; 689 ret = dapm_create_or_share_mixmux_kcontrol(w, 0, path);
688 690 if (ret < 0)
689 w->kcontrols[0] = kcontrol; 691 return ret;
690 692
691 list_for_each_entry(path, &w->sources, list_sink) 693 list_for_each_entry(path, &w->sources, list_sink)
692 path->kcontrol = kcontrol; 694 path->kcontrol = w->kcontrols[0];
693 695
694 return 0; 696 return 0;
695} 697}
@@ -705,14 +707,33 @@ static int dapm_new_pga(struct snd_soc_dapm_widget *w)
705} 707}
706 708
707/* reset 'walked' bit for each dapm path */ 709/* reset 'walked' bit for each dapm path */
708static inline void dapm_clear_walk(struct snd_soc_dapm_context *dapm) 710static void dapm_clear_walk_output(struct snd_soc_dapm_context *dapm,
711 struct list_head *sink)
709{ 712{
710 struct snd_soc_dapm_path *p; 713 struct snd_soc_dapm_path *p;
711 714
712 list_for_each_entry(p, &dapm->card->paths, list) 715 list_for_each_entry(p, sink, list_source) {
713 p->walked = 0; 716 if (p->walked) {
717 p->walked = 0;
718 dapm_clear_walk_output(dapm, &p->sink->sinks);
719 }
720 }
714} 721}
715 722
723static void dapm_clear_walk_input(struct snd_soc_dapm_context *dapm,
724 struct list_head *source)
725{
726 struct snd_soc_dapm_path *p;
727
728 list_for_each_entry(p, source, list_sink) {
729 if (p->walked) {
730 p->walked = 0;
731 dapm_clear_walk_input(dapm, &p->source->sources);
732 }
733 }
734}
735
736
716/* We implement power down on suspend by checking the power state of 737/* We implement power down on suspend by checking the power state of
717 * the ALSA card - when we are suspending the ALSA state for the card 738 * the ALSA card - when we are suspending the ALSA state for the card
718 * is set to D3. 739 * is set to D3.
@@ -995,13 +1016,17 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
995 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 1016 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
996 dapm_reset(card); 1017 dapm_reset(card);
997 1018
998 if (stream == SNDRV_PCM_STREAM_PLAYBACK) 1019 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
999 paths = is_connected_output_ep(dai->playback_widget, list); 1020 paths = is_connected_output_ep(dai->playback_widget, list);
1000 else 1021 dapm_clear_walk_output(&card->dapm,
1022 &dai->playback_widget->sinks);
1023 } else {
1001 paths = is_connected_input_ep(dai->capture_widget, list); 1024 paths = is_connected_input_ep(dai->capture_widget, list);
1025 dapm_clear_walk_input(&card->dapm,
1026 &dai->capture_widget->sources);
1027 }
1002 1028
1003 trace_snd_soc_dapm_connected(paths, stream); 1029 trace_snd_soc_dapm_connected(paths, stream);
1004 dapm_clear_walk(&card->dapm);
1005 mutex_unlock(&card->dapm_mutex); 1030 mutex_unlock(&card->dapm_mutex);
1006 1031
1007 return paths; 1032 return paths;
@@ -1104,9 +1129,9 @@ static int dapm_generic_check_power(struct snd_soc_dapm_widget *w)
1104 DAPM_UPDATE_STAT(w, power_checks); 1129 DAPM_UPDATE_STAT(w, power_checks);
1105 1130
1106 in = is_connected_input_ep(w, NULL); 1131 in = is_connected_input_ep(w, NULL);
1107 dapm_clear_walk(w->dapm); 1132 dapm_clear_walk_input(w->dapm, &w->sources);
1108 out = is_connected_output_ep(w, NULL); 1133 out = is_connected_output_ep(w, NULL);
1109 dapm_clear_walk(w->dapm); 1134 dapm_clear_walk_output(w->dapm, &w->sinks);
1110 return out != 0 && in != 0; 1135 return out != 0 && in != 0;
1111} 1136}
1112 1137
@@ -1129,7 +1154,7 @@ static int dapm_adc_check_power(struct snd_soc_dapm_widget *w)
1129 1154
1130 if (w->active) { 1155 if (w->active) {
1131 in = is_connected_input_ep(w, NULL); 1156 in = is_connected_input_ep(w, NULL);
1132 dapm_clear_walk(w->dapm); 1157 dapm_clear_walk_input(w->dapm, &w->sources);
1133 return in != 0; 1158 return in != 0;
1134 } else { 1159 } else {
1135 return dapm_generic_check_power(w); 1160 return dapm_generic_check_power(w);
@@ -1145,7 +1170,7 @@ static int dapm_dac_check_power(struct snd_soc_dapm_widget *w)
1145 1170
1146 if (w->active) { 1171 if (w->active) {
1147 out = is_connected_output_ep(w, NULL); 1172 out = is_connected_output_ep(w, NULL);
1148 dapm_clear_walk(w->dapm); 1173 dapm_clear_walk_output(w->dapm, &w->sinks);
1149 return out != 0; 1174 return out != 0;
1150 } else { 1175 } else {
1151 return dapm_generic_check_power(w); 1176 return dapm_generic_check_power(w);
@@ -1177,8 +1202,6 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
1177 return 1; 1202 return 1;
1178 } 1203 }
1179 1204
1180 dapm_clear_walk(w->dapm);
1181
1182 return 0; 1205 return 0;
1183} 1206}
1184 1207
@@ -1759,9 +1782,9 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
1759 return -ENOMEM; 1782 return -ENOMEM;
1760 1783
1761 in = is_connected_input_ep(w, NULL); 1784 in = is_connected_input_ep(w, NULL);
1762 dapm_clear_walk(w->dapm); 1785 dapm_clear_walk_input(w->dapm, &w->sources);
1763 out = is_connected_output_ep(w, NULL); 1786 out = is_connected_output_ep(w, NULL);
1764 dapm_clear_walk(w->dapm); 1787 dapm_clear_walk_output(w->dapm, &w->sinks);
1765 1788
1766 ret = snprintf(buf, PAGE_SIZE, "%s: %s%s in %d out %d", 1789 ret = snprintf(buf, PAGE_SIZE, "%s: %s%s in %d out %d",
1767 w->name, w->power ? "On" : "Off", 1790 w->name, w->power ? "On" : "Off",
@@ -3137,7 +3160,6 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
3137 break; 3160 break;
3138 } 3161 }
3139 3162
3140 dapm->n_widgets++;
3141 w->dapm = dapm; 3163 w->dapm = dapm;
3142 w->codec = dapm->codec; 3164 w->codec = dapm->codec;
3143 w->platform = dapm->platform; 3165 w->platform = dapm->platform;
diff --git a/sound/soc/soc-dmaengine-pcm.c b/sound/soc/soc-dmaengine-pcm.c
index 111b7d921e89..aa924d9b7986 100644
--- a/sound/soc/soc-dmaengine-pcm.c
+++ b/sound/soc/soc-dmaengine-pcm.c
@@ -33,8 +33,6 @@ struct dmaengine_pcm_runtime_data {
33 dma_cookie_t cookie; 33 dma_cookie_t cookie;
34 34
35 unsigned int pos; 35 unsigned int pos;
36
37 void *data;
38}; 36};
39 37
40static inline struct dmaengine_pcm_runtime_data *substream_to_prtd( 38static inline struct dmaengine_pcm_runtime_data *substream_to_prtd(
@@ -43,33 +41,6 @@ static inline struct dmaengine_pcm_runtime_data *substream_to_prtd(
43 return substream->runtime->private_data; 41 return substream->runtime->private_data;
44} 42}
45 43
46/**
47 * snd_dmaengine_pcm_set_data - Set dmaengine substream private data
48 * @substream: PCM substream
49 * @data: Data to set
50 */
51void snd_dmaengine_pcm_set_data(struct snd_pcm_substream *substream, void *data)
52{
53 struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
54
55 prtd->data = data;
56}
57EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_data);
58
59/**
60 * snd_dmaengine_pcm_get_data - Get dmaeinge substream private data
61 * @substream: PCM substream
62 *
63 * Returns the data previously set with snd_dmaengine_pcm_set_data
64 */
65void *snd_dmaengine_pcm_get_data(struct snd_pcm_substream *substream)
66{
67 struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
68
69 return prtd->data;
70}
71EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_get_data);
72
73struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream) 44struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream)
74{ 45{
75 struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); 46 struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
@@ -118,10 +89,49 @@ int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream,
118 slave_config->src_addr_width = buswidth; 89 slave_config->src_addr_width = buswidth;
119 } 90 }
120 91
92 slave_config->device_fc = false;
93
121 return 0; 94 return 0;
122} 95}
123EXPORT_SYMBOL_GPL(snd_hwparams_to_dma_slave_config); 96EXPORT_SYMBOL_GPL(snd_hwparams_to_dma_slave_config);
124 97
98/**
99 * snd_dmaengine_pcm_set_config_from_dai_data() - Initializes a dma slave config
100 * using DAI DMA data.
101 * @substream: PCM substream
102 * @dma_data: DAI DMA data
103 * @slave_config: DMA slave configuration
104 *
105 * Initializes the {dst,src}_addr, {dst,src}_maxburst, {dst,src}_addr_width and
106 * slave_id fields of the DMA slave config from the same fields of the DAI DMA
107 * data struct. The src and dst fields will be initialized depending on the
108 * direction of the substream. If the substream is a playback stream the dst
109 * fields will be initialized, if it is a capture stream the src fields will be
110 * initialized. The {dst,src}_addr_width field will only be initialized if the
111 * addr_width field of the DAI DMA data struct is not equal to
112 * DMA_SLAVE_BUSWIDTH_UNDEFINED.
113 */
114void snd_dmaengine_pcm_set_config_from_dai_data(
115 const struct snd_pcm_substream *substream,
116 const struct snd_dmaengine_dai_dma_data *dma_data,
117 struct dma_slave_config *slave_config)
118{
119 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
120 slave_config->dst_addr = dma_data->addr;
121 slave_config->dst_maxburst = dma_data->maxburst;
122 if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED)
123 slave_config->dst_addr_width = dma_data->addr_width;
124 } else {
125 slave_config->src_addr = dma_data->addr;
126 slave_config->src_maxburst = dma_data->maxburst;
127 if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED)
128 slave_config->src_addr_width = dma_data->addr_width;
129 }
130
131 slave_config->slave_id = dma_data->slave_id;
132}
133EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data);
134
125static void dmaengine_pcm_dma_complete(void *arg) 135static void dmaengine_pcm_dma_complete(void *arg)
126{ 136{
127 struct snd_pcm_substream *substream = arg; 137 struct snd_pcm_substream *substream = arg;
@@ -244,44 +254,48 @@ snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream)
244} 254}
245EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer); 255EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer);
246 256
247static int dmaengine_pcm_request_channel(struct dmaengine_pcm_runtime_data *prtd, 257/**
248 dma_filter_fn filter_fn, void *filter_data) 258 * snd_dmaengine_pcm_request_channel - Request channel for the dmaengine PCM
259 * @filter_fn: Filter function used to request the DMA channel
260 * @filter_data: Data passed to the DMA filter function
261 *
262 * Returns NULL or the requested DMA channel.
263 *
264 * This function request a DMA channel for usage with dmaengine PCM.
265 */
266struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn,
267 void *filter_data)
249{ 268{
250 dma_cap_mask_t mask; 269 dma_cap_mask_t mask;
251 270
252 dma_cap_zero(mask); 271 dma_cap_zero(mask);
253 dma_cap_set(DMA_SLAVE, mask); 272 dma_cap_set(DMA_SLAVE, mask);
254 dma_cap_set(DMA_CYCLIC, mask); 273 dma_cap_set(DMA_CYCLIC, mask);
255 prtd->dma_chan = dma_request_channel(mask, filter_fn, filter_data);
256 274
257 if (!prtd->dma_chan) 275 return dma_request_channel(mask, filter_fn, filter_data);
258 return -ENXIO;
259
260 return 0;
261} 276}
277EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_request_channel);
262 278
263/** 279/**
264 * snd_dmaengine_pcm_open - Open a dmaengine based PCM substream 280 * snd_dmaengine_pcm_open - Open a dmaengine based PCM substream
265 * @substream: PCM substream 281 * @substream: PCM substream
266 * @filter_fn: Filter function used to request the DMA channel 282 * @chan: DMA channel to use for data transfers
267 * @filter_data: Data passed to the DMA filter function
268 * 283 *
269 * Returns 0 on success, a negative error code otherwise. 284 * Returns 0 on success, a negative error code otherwise.
270 * 285 *
271 * This function will request a DMA channel using the passed filter function and 286 * The function should usually be called from the pcm open callback. Note that
272 * data. The function should usually be called from the pcm open callback. 287 * this function will use private_data field of the substream's runtime. So it
273 * 288 * is not availabe to your pcm driver implementation.
274 * Note that this function will use private_data field of the substream's
275 * runtime. So it is not availabe to your pcm driver implementation. If you need
276 * to keep additional data attached to a substream use
277 * snd_dmaengine_pcm_{set,get}_data.
278 */ 289 */
279int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, 290int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
280 dma_filter_fn filter_fn, void *filter_data) 291 struct dma_chan *chan)
281{ 292{
282 struct dmaengine_pcm_runtime_data *prtd; 293 struct dmaengine_pcm_runtime_data *prtd;
283 int ret; 294 int ret;
284 295
296 if (!chan)
297 return -ENXIO;
298
285 ret = snd_pcm_hw_constraint_integer(substream->runtime, 299 ret = snd_pcm_hw_constraint_integer(substream->runtime,
286 SNDRV_PCM_HW_PARAM_PERIODS); 300 SNDRV_PCM_HW_PARAM_PERIODS);
287 if (ret < 0) 301 if (ret < 0)
@@ -291,11 +305,7 @@ int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
291 if (!prtd) 305 if (!prtd)
292 return -ENOMEM; 306 return -ENOMEM;
293 307
294 ret = dmaengine_pcm_request_channel(prtd, filter_fn, filter_data); 308 prtd->dma_chan = chan;
295 if (ret < 0) {
296 kfree(prtd);
297 return ret;
298 }
299 309
300 substream->runtime->private_data = prtd; 310 substream->runtime->private_data = prtd;
301 311
@@ -304,6 +314,27 @@ int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
304EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open); 314EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open);
305 315
306/** 316/**
317 * snd_dmaengine_pcm_open_request_chan - Open a dmaengine based PCM substream and request channel
318 * @substream: PCM substream
319 * @filter_fn: Filter function used to request the DMA channel
320 * @filter_data: Data passed to the DMA filter function
321 *
322 * Returns 0 on success, a negative error code otherwise.
323 *
324 * This function will request a DMA channel using the passed filter function and
325 * data. The function should usually be called from the pcm open callback. Note
326 * that this function will use private_data field of the substream's runtime. So
327 * it is not availabe to your pcm driver implementation.
328 */
329int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream,
330 dma_filter_fn filter_fn, void *filter_data)
331{
332 return snd_dmaengine_pcm_open(substream,
333 snd_dmaengine_pcm_request_channel(filter_fn, filter_data));
334}
335EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_chan);
336
337/**
307 * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream 338 * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream
308 * @substream: PCM substream 339 * @substream: PCM substream
309 */ 340 */
@@ -311,11 +342,26 @@ int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream)
311{ 342{
312 struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); 343 struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
313 344
314 dma_release_channel(prtd->dma_chan);
315 kfree(prtd); 345 kfree(prtd);
316 346
317 return 0; 347 return 0;
318} 348}
319EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close); 349EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close);
320 350
351/**
352 * snd_dmaengine_pcm_release_chan_close - Close a dmaengine based PCM substream and release channel
353 * @substream: PCM substream
354 *
355 * Releases the DMA channel associated with the PCM substream.
356 */
357int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream)
358{
359 struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
360
361 dma_release_channel(prtd->dma_chan);
362
363 return snd_dmaengine_pcm_close(substream);
364}
365EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close_release_chan);
366
321MODULE_LICENSE("GPL"); 367MODULE_LICENSE("GPL");
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c
new file mode 100644
index 000000000000..e29ec3cd84b1
--- /dev/null
+++ b/sound/soc/soc-generic-dmaengine-pcm.c
@@ -0,0 +1,300 @@
1/*
2 * Copyright (C) 2013, Analog Devices Inc.
3 * Author: Lars-Peter Clausen <lars@metafoo.de>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * You should have received a copy of the GNU General Public License along
11 * with this program; if not, write to the Free Software Foundation, Inc.,
12 * 675 Mass Ave, Cambridge, MA 02139, USA.
13 *
14 */
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/dmaengine.h>
18#include <linux/slab.h>
19#include <sound/pcm.h>
20#include <sound/pcm_params.h>
21#include <sound/soc.h>
22#include <linux/dma-mapping.h>
23#include <linux/of.h>
24
25#include <sound/dmaengine_pcm.h>
26
27struct dmaengine_pcm {
28 struct dma_chan *chan[SNDRV_PCM_STREAM_CAPTURE + 1];
29 const struct snd_dmaengine_pcm_config *config;
30 struct snd_soc_platform platform;
31 unsigned int flags;
32};
33
34static struct dmaengine_pcm *soc_platform_to_pcm(struct snd_soc_platform *p)
35{
36 return container_of(p, struct dmaengine_pcm, platform);
37}
38
39/**
40 * snd_dmaengine_pcm_prepare_slave_config() - Generic prepare_slave_config callback
41 * @substream: PCM substream
42 * @params: hw_params
43 * @slave_config: DMA slave config to prepare
44 *
45 * This function can be used as a generic prepare_slave_config callback for
46 * platforms which make use of the snd_dmaengine_dai_dma_data struct for their
47 * DAI DMA data. Internally the function will first call
48 * snd_hwparams_to_dma_slave_config to fill in the slave config based on the
49 * hw_params, followed by snd_dmaengine_set_config_from_dai_data to fill in the
50 * remaining fields based on the DAI DMA data.
51 */
52int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream,
53 struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config)
54{
55 struct snd_soc_pcm_runtime *rtd = substream->private_data;
56 struct snd_dmaengine_dai_dma_data *dma_data;
57 int ret;
58
59 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
60
61 ret = snd_hwparams_to_dma_slave_config(substream, params, slave_config);
62 if (ret)
63 return ret;
64
65 snd_dmaengine_pcm_set_config_from_dai_data(substream, dma_data,
66 slave_config);
67
68 return 0;
69}
70EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_prepare_slave_config);
71
72static int dmaengine_pcm_hw_params(struct snd_pcm_substream *substream,
73 struct snd_pcm_hw_params *params)
74{
75 struct snd_soc_pcm_runtime *rtd = substream->private_data;
76 struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform);
77 struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
78 struct dma_slave_config slave_config;
79 int ret;
80
81 if (pcm->config->prepare_slave_config) {
82 ret = pcm->config->prepare_slave_config(substream, params,
83 &slave_config);
84 if (ret)
85 return ret;
86
87 ret = dmaengine_slave_config(chan, &slave_config);
88 if (ret)
89 return ret;
90 }
91
92 return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
93}
94
95static int dmaengine_pcm_open(struct snd_pcm_substream *substream)
96{
97 struct snd_soc_pcm_runtime *rtd = substream->private_data;
98 struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform);
99 struct dma_chan *chan = pcm->chan[substream->stream];
100 int ret;
101
102 ret = snd_soc_set_runtime_hwparams(substream,
103 pcm->config->pcm_hardware);
104 if (ret)
105 return ret;
106
107 return snd_dmaengine_pcm_open(substream, chan);
108}
109
110static struct device *dmaengine_dma_dev(struct dmaengine_pcm *pcm,
111 struct snd_pcm_substream *substream)
112{
113 if (!pcm->chan[substream->stream])
114 return NULL;
115
116 return pcm->chan[substream->stream]->device->dev;
117}
118
119static void dmaengine_pcm_free(struct snd_pcm *pcm)
120{
121 snd_pcm_lib_preallocate_free_for_all(pcm);
122}
123
124static struct dma_chan *dmaengine_pcm_compat_request_channel(
125 struct snd_soc_pcm_runtime *rtd,
126 struct snd_pcm_substream *substream)
127{
128 struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform);
129
130 if ((pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) && pcm->chan[0])
131 return pcm->chan[0];
132
133 if (pcm->config->compat_request_channel)
134 return pcm->config->compat_request_channel(rtd, substream);
135
136 return snd_dmaengine_pcm_request_channel(pcm->config->compat_filter_fn,
137 snd_soc_dai_get_dma_data(rtd->cpu_dai, substream));
138}
139
140static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd)
141{
142 struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform);
143 const struct snd_dmaengine_pcm_config *config = pcm->config;
144 struct snd_pcm_substream *substream;
145 unsigned int i;
146 int ret;
147
148 for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) {
149 substream = rtd->pcm->streams[i].substream;
150 if (!substream)
151 continue;
152
153 if (!pcm->chan[i] && (pcm->flags & SND_DMAENGINE_PCM_FLAG_COMPAT)) {
154 pcm->chan[i] = dmaengine_pcm_compat_request_channel(rtd,
155 substream);
156 }
157
158 if (!pcm->chan[i]) {
159 dev_err(rtd->platform->dev,
160 "Missing dma channel for stream: %d\n", i);
161 ret = -EINVAL;
162 goto err_free;
163 }
164
165 ret = snd_pcm_lib_preallocate_pages(substream,
166 SNDRV_DMA_TYPE_DEV,
167 dmaengine_dma_dev(pcm, substream),
168 config->prealloc_buffer_size,
169 config->pcm_hardware->buffer_bytes_max);
170 if (ret)
171 goto err_free;
172 }
173
174 return 0;
175
176err_free:
177 dmaengine_pcm_free(rtd->pcm);
178 return ret;
179}
180
181static const struct snd_pcm_ops dmaengine_pcm_ops = {
182 .open = dmaengine_pcm_open,
183 .close = snd_dmaengine_pcm_close,
184 .ioctl = snd_pcm_lib_ioctl,
185 .hw_params = dmaengine_pcm_hw_params,
186 .hw_free = snd_pcm_lib_free_pages,
187 .trigger = snd_dmaengine_pcm_trigger,
188 .pointer = snd_dmaengine_pcm_pointer,
189};
190
191static const struct snd_soc_platform_driver dmaengine_pcm_platform = {
192 .ops = &dmaengine_pcm_ops,
193 .pcm_new = dmaengine_pcm_new,
194 .pcm_free = dmaengine_pcm_free,
195 .probe_order = SND_SOC_COMP_ORDER_LATE,
196};
197
198static const struct snd_pcm_ops dmaengine_no_residue_pcm_ops = {
199 .open = dmaengine_pcm_open,
200 .close = snd_dmaengine_pcm_close,
201 .ioctl = snd_pcm_lib_ioctl,
202 .hw_params = dmaengine_pcm_hw_params,
203 .hw_free = snd_pcm_lib_free_pages,
204 .trigger = snd_dmaengine_pcm_trigger,
205 .pointer = snd_dmaengine_pcm_pointer_no_residue,
206};
207
208static const struct snd_soc_platform_driver dmaengine_no_residue_pcm_platform = {
209 .ops = &dmaengine_no_residue_pcm_ops,
210 .pcm_new = dmaengine_pcm_new,
211 .pcm_free = dmaengine_pcm_free,
212 .probe_order = SND_SOC_COMP_ORDER_LATE,
213};
214
215static const char * const dmaengine_pcm_dma_channel_names[] = {
216 [SNDRV_PCM_STREAM_PLAYBACK] = "tx",
217 [SNDRV_PCM_STREAM_CAPTURE] = "rx",
218};
219
220static void dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm,
221 struct device *dev)
222{
223 unsigned int i;
224
225 if ((pcm->flags & SND_DMAENGINE_PCM_FLAG_NO_DT) || !dev->of_node)
226 return;
227
228 if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) {
229 pcm->chan[0] = dma_request_slave_channel(dev, "rx-tx");
230 pcm->chan[1] = pcm->chan[0];
231 } else {
232 for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) {
233 pcm->chan[i] = dma_request_slave_channel(dev,
234 dmaengine_pcm_dma_channel_names[i]);
235 }
236 }
237}
238
239/**
240 * snd_dmaengine_pcm_register - Register a dmaengine based PCM device
241 * @dev: The parent device for the PCM device
242 * @config: Platform specific PCM configuration
243 * @flags: Platform specific quirks
244 */
245int snd_dmaengine_pcm_register(struct device *dev,
246 const struct snd_dmaengine_pcm_config *config, unsigned int flags)
247{
248 struct dmaengine_pcm *pcm;
249
250 pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
251 if (!pcm)
252 return -ENOMEM;
253
254 pcm->config = config;
255 pcm->flags = flags;
256
257 dmaengine_pcm_request_chan_of(pcm, dev);
258
259 if (flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE)
260 return snd_soc_add_platform(dev, &pcm->platform,
261 &dmaengine_no_residue_pcm_platform);
262 else
263 return snd_soc_add_platform(dev, &pcm->platform,
264 &dmaengine_pcm_platform);
265}
266EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_register);
267
268/**
269 * snd_dmaengine_pcm_unregister - Removes a dmaengine based PCM device
270 * @dev: Parent device the PCM was register with
271 *
272 * Removes a dmaengine based PCM device previously registered with
273 * snd_dmaengine_pcm_register.
274 */
275void snd_dmaengine_pcm_unregister(struct device *dev)
276{
277 struct snd_soc_platform *platform;
278 struct dmaengine_pcm *pcm;
279 unsigned int i;
280
281 platform = snd_soc_lookup_platform(dev);
282 if (!platform)
283 return;
284
285 pcm = soc_platform_to_pcm(platform);
286
287 for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) {
288 if (pcm->chan[i]) {
289 dma_release_channel(pcm->chan[i]);
290 if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
291 break;
292 }
293 }
294
295 snd_soc_remove_platform(platform);
296 kfree(pcm);
297}
298EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_unregister);
299
300MODULE_LICENSE("GPL");
diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c
index 29183ef2b93d..8ca9ecc5ac57 100644
--- a/sound/soc/soc-io.c
+++ b/sound/soc/soc-io.c
@@ -158,10 +158,7 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
158 return -EINVAL; 158 return -EINVAL;
159 } 159 }
160 160
161 if (IS_ERR(codec->control_data)) 161 return PTR_RET(codec->control_data);
162 return PTR_ERR(codec->control_data);
163
164 return 0;
165} 162}
166EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io); 163EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);
167#else 164#else
diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c
index fe4541df498c..4b3be6c3c91e 100644
--- a/sound/soc/soc-utils.c
+++ b/sound/soc/soc-utils.c
@@ -90,8 +90,33 @@ static struct snd_soc_platform_driver dummy_platform = {
90}; 90};
91 91
92static struct snd_soc_codec_driver dummy_codec; 92static struct snd_soc_codec_driver dummy_codec;
93
94#define STUB_RATES SNDRV_PCM_RATE_8000_192000
95#define STUB_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
96 SNDRV_PCM_FMTBIT_U8 | \
97 SNDRV_PCM_FMTBIT_S16_LE | \
98 SNDRV_PCM_FMTBIT_U16_LE | \
99 SNDRV_PCM_FMTBIT_S24_LE | \
100 SNDRV_PCM_FMTBIT_U24_LE | \
101 SNDRV_PCM_FMTBIT_S32_LE | \
102 SNDRV_PCM_FMTBIT_U32_LE | \
103 SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)
93static struct snd_soc_dai_driver dummy_dai = { 104static struct snd_soc_dai_driver dummy_dai = {
94 .name = "snd-soc-dummy-dai", 105 .name = "snd-soc-dummy-dai",
106 .playback = {
107 .stream_name = "Playback",
108 .channels_min = 1,
109 .channels_max = 384,
110 .rates = STUB_RATES,
111 .formats = STUB_FORMATS,
112 },
113 .capture = {
114 .stream_name = "Capture",
115 .channels_min = 1,
116 .channels_max = 384,
117 .rates = STUB_RATES,
118 .formats = STUB_FORMATS,
119 },
95}; 120};
96 121
97static int snd_soc_dummy_probe(struct platform_device *pdev) 122static int snd_soc_dummy_probe(struct platform_device *pdev)
diff --git a/sound/soc/spear/spdif_in.c b/sound/soc/spear/spdif_in.c
index c7c4b20395bb..14d57e89bcba 100644
--- a/sound/soc/spear/spdif_in.c
+++ b/sound/soc/spear/spdif_in.c
@@ -170,6 +170,10 @@ struct snd_soc_dai_driver spdif_in_dai = {
170 .ops = &spdif_in_dai_ops, 170 .ops = &spdif_in_dai_ops,
171}; 171};
172 172
173static const struct snd_soc_component_driver spdif_in_component = {
174 .name = "spdif-in",
175};
176
173static irqreturn_t spdif_in_irq(int irq, void *arg) 177static irqreturn_t spdif_in_irq(int irq, void *arg)
174{ 178{
175 struct spdif_in_dev *host = (struct spdif_in_dev *)arg; 179 struct spdif_in_dev *host = (struct spdif_in_dev *)arg;
@@ -258,7 +262,8 @@ static int spdif_in_probe(struct platform_device *pdev)
258 return ret; 262 return ret;
259 } 263 }
260 264
261 ret = snd_soc_register_dai(&pdev->dev, &spdif_in_dai); 265 ret = snd_soc_register_component(&pdev->dev, &spdif_in_component,
266 &spdif_in_dai, 1);
262 if (ret != 0) { 267 if (ret != 0) {
263 clk_put(host->clk); 268 clk_put(host->clk);
264 return ret; 269 return ret;
@@ -271,7 +276,7 @@ static int spdif_in_remove(struct platform_device *pdev)
271{ 276{
272 struct spdif_in_dev *host = dev_get_drvdata(&pdev->dev); 277 struct spdif_in_dev *host = dev_get_drvdata(&pdev->dev);
273 278
274 snd_soc_unregister_dai(&pdev->dev); 279 snd_soc_unregister_component(&pdev->dev);
275 dev_set_drvdata(&pdev->dev, NULL); 280 dev_set_drvdata(&pdev->dev, NULL);
276 281
277 clk_put(host->clk); 282 clk_put(host->clk);
diff --git a/sound/soc/spear/spdif_out.c b/sound/soc/spear/spdif_out.c
index 5eac4cda2fd7..1e3c3dda3598 100644
--- a/sound/soc/spear/spdif_out.c
+++ b/sound/soc/spear/spdif_out.c
@@ -270,6 +270,10 @@ static struct snd_soc_dai_driver spdif_out_dai = {
270 .ops = &spdif_out_dai_ops, 270 .ops = &spdif_out_dai_ops,
271}; 271};
272 272
273static const struct snd_soc_component_driver spdif_out_component = {
274 .name = "spdif-out",
275};
276
273static int spdif_out_probe(struct platform_device *pdev) 277static int spdif_out_probe(struct platform_device *pdev)
274{ 278{
275 struct spdif_out_dev *host; 279 struct spdif_out_dev *host;
@@ -314,7 +318,8 @@ static int spdif_out_probe(struct platform_device *pdev)
314 318
315 dev_set_drvdata(&pdev->dev, host); 319 dev_set_drvdata(&pdev->dev, host);
316 320
317 ret = snd_soc_register_dai(&pdev->dev, &spdif_out_dai); 321 ret = snd_soc_register_component(&pdev->dev, &spdif_out_component,
322 &spdif_out_dai, 1);
318 if (ret != 0) { 323 if (ret != 0) {
319 clk_put(host->clk); 324 clk_put(host->clk);
320 return ret; 325 return ret;
@@ -327,7 +332,7 @@ static int spdif_out_remove(struct platform_device *pdev)
327{ 332{
328 struct spdif_out_dev *host = dev_get_drvdata(&pdev->dev); 333 struct spdif_out_dev *host = dev_get_drvdata(&pdev->dev);
329 334
330 snd_soc_unregister_dai(&pdev->dev); 335 snd_soc_unregister_component(&pdev->dev);
331 dev_set_drvdata(&pdev->dev, NULL); 336 dev_set_drvdata(&pdev->dev, NULL);
332 337
333 clk_put(host->clk); 338 clk_put(host->clk);
diff --git a/sound/soc/spear/spear_pcm.c b/sound/soc/spear/spear_pcm.c
index 5e7aebe1e664..2fbd4899d8ef 100644
--- a/sound/soc/spear/spear_pcm.c
+++ b/sound/soc/spear/spear_pcm.c
@@ -25,7 +25,7 @@
25#include <sound/soc.h> 25#include <sound/soc.h>
26#include <sound/spear_dma.h> 26#include <sound/spear_dma.h>
27 27
28struct snd_pcm_hardware spear_pcm_hardware = { 28static struct snd_pcm_hardware spear_pcm_hardware = {
29 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | 29 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
30 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | 30 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
31 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), 31 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
@@ -64,21 +64,8 @@ static int spear_pcm_open(struct snd_pcm_substream *substream)
64 if (ret) 64 if (ret)
65 return ret; 65 return ret;
66 66
67 ret = snd_dmaengine_pcm_open(substream, dma_data->filter, dma_data); 67 return snd_dmaengine_pcm_open_request_chan(substream, dma_data->filter,
68 if (ret) 68 dma_data);
69 return ret;
70
71 snd_dmaengine_pcm_set_data(substream, dma_data);
72
73 return 0;
74}
75
76static int spear_pcm_close(struct snd_pcm_substream *substream)
77{
78
79 snd_dmaengine_pcm_close(substream);
80
81 return 0;
82} 69}
83 70
84static int spear_pcm_mmap(struct snd_pcm_substream *substream, 71static int spear_pcm_mmap(struct snd_pcm_substream *substream,
@@ -93,7 +80,7 @@ static int spear_pcm_mmap(struct snd_pcm_substream *substream,
93 80
94static struct snd_pcm_ops spear_pcm_ops = { 81static struct snd_pcm_ops spear_pcm_ops = {
95 .open = spear_pcm_open, 82 .open = spear_pcm_open,
96 .close = spear_pcm_close, 83 .close = snd_dmaengine_pcm_close_release_chan,
97 .ioctl = snd_pcm_lib_ioctl, 84 .ioctl = snd_pcm_lib_ioctl,
98 .hw_params = spear_pcm_hw_params, 85 .hw_params = spear_pcm_hw_params,
99 .hw_free = spear_pcm_hw_free, 86 .hw_free = spear_pcm_hw_free,
@@ -178,7 +165,7 @@ static int spear_pcm_new(struct snd_soc_pcm_runtime *rtd)
178 return 0; 165 return 0;
179} 166}
180 167
181struct snd_soc_platform_driver spear_soc_platform = { 168static struct snd_soc_platform_driver spear_soc_platform = {
182 .ops = &spear_pcm_ops, 169 .ops = &spear_pcm_ops,
183 .pcm_new = spear_pcm_new, 170 .pcm_new = spear_pcm_new,
184 .pcm_free = spear_pcm_free, 171 .pcm_free = spear_pcm_free,
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index dbc27ce1d4de..b1c9d573da05 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -2,7 +2,7 @@ config SND_SOC_TEGRA
2 tristate "SoC Audio for the Tegra System-on-Chip" 2 tristate "SoC Audio for the Tegra System-on-Chip"
3 depends on ARCH_TEGRA && TEGRA20_APB_DMA 3 depends on ARCH_TEGRA && TEGRA20_APB_DMA
4 select REGMAP_MMIO 4 select REGMAP_MMIO
5 select SND_SOC_DMAENGINE_PCM if TEGRA20_APB_DMA 5 select SND_SOC_GENERIC_DMAENGINE_PCM if TEGRA20_APB_DMA
6 help 6 help
7 Say Y or M here if you want support for SoC audio on Tegra. 7 Say Y or M here if you want support for SoC audio on Tegra.
8 8
diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c
index 336dcdd3e8a4..2f70ea7f6618 100644
--- a/sound/soc/tegra/tegra20_ac97.c
+++ b/sound/soc/tegra/tegra20_ac97.c
@@ -35,6 +35,7 @@
35#include <sound/pcm.h> 35#include <sound/pcm.h>
36#include <sound/pcm_params.h> 36#include <sound/pcm_params.h>
37#include <sound/soc.h> 37#include <sound/soc.h>
38#include <sound/dmaengine_pcm.h>
38 39
39#include "tegra_asoc_utils.h" 40#include "tegra_asoc_utils.h"
40#include "tegra20_ac97.h" 41#include "tegra20_ac97.h"
@@ -248,6 +249,10 @@ static struct snd_soc_dai_driver tegra20_ac97_dai = {
248 .ops = &tegra20_ac97_dai_ops, 249 .ops = &tegra20_ac97_dai_ops,
249}; 250};
250 251
252static const struct snd_soc_component_driver tegra20_ac97_component = {
253 .name = DRV_NAME,
254};
255
251static bool tegra20_ac97_wr_rd_reg(struct device *dev, unsigned int reg) 256static bool tegra20_ac97_wr_rd_reg(struct device *dev, unsigned int reg)
252{ 257{
253 switch (reg) { 258 switch (reg) {
@@ -389,16 +394,17 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev)
389 } 394 }
390 395
391 ac97->capture_dma_data.addr = mem->start + TEGRA20_AC97_FIFO_RX1; 396 ac97->capture_dma_data.addr = mem->start + TEGRA20_AC97_FIFO_RX1;
392 ac97->capture_dma_data.wrap = 4; 397 ac97->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
393 ac97->capture_dma_data.width = 32; 398 ac97->capture_dma_data.maxburst = 4;
394 ac97->capture_dma_data.req_sel = of_dma[1]; 399 ac97->capture_dma_data.slave_id = of_dma[1];
395 400
396 ac97->playback_dma_data.addr = mem->start + TEGRA20_AC97_FIFO_TX1; 401 ac97->playback_dma_data.addr = mem->start + TEGRA20_AC97_FIFO_TX1;
397 ac97->playback_dma_data.wrap = 4; 402 ac97->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
398 ac97->playback_dma_data.width = 32; 403 ac97->capture_dma_data.maxburst = 4;
399 ac97->playback_dma_data.req_sel = of_dma[1]; 404 ac97->capture_dma_data.slave_id = of_dma[0];
400 405
401 ret = snd_soc_register_dais(&pdev->dev, &tegra20_ac97_dai, 1); 406 ret = snd_soc_register_component(&pdev->dev, &tegra20_ac97_component,
407 &tegra20_ac97_dai, 1);
402 if (ret) { 408 if (ret) {
403 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); 409 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
404 ret = -ENOMEM; 410 ret = -ENOMEM;
@@ -408,7 +414,7 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev)
408 ret = tegra_pcm_platform_register(&pdev->dev); 414 ret = tegra_pcm_platform_register(&pdev->dev);
409 if (ret) { 415 if (ret) {
410 dev_err(&pdev->dev, "Could not register PCM: %d\n", ret); 416 dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
411 goto err_unregister_dai; 417 goto err_unregister_component;
412 } 418 }
413 419
414 ret = tegra_asoc_utils_init(&ac97->util_data, &pdev->dev); 420 ret = tegra_asoc_utils_init(&ac97->util_data, &pdev->dev);
@@ -434,8 +440,8 @@ err_asoc_utils_fini:
434 tegra_asoc_utils_fini(&ac97->util_data); 440 tegra_asoc_utils_fini(&ac97->util_data);
435err_unregister_pcm: 441err_unregister_pcm:
436 tegra_pcm_platform_unregister(&pdev->dev); 442 tegra_pcm_platform_unregister(&pdev->dev);
437err_unregister_dai: 443err_unregister_component:
438 snd_soc_unregister_dai(&pdev->dev); 444 snd_soc_unregister_component(&pdev->dev);
439err_clk_put: 445err_clk_put:
440 clk_put(ac97->clk_ac97); 446 clk_put(ac97->clk_ac97);
441err: 447err:
@@ -447,7 +453,7 @@ static int tegra20_ac97_platform_remove(struct platform_device *pdev)
447 struct tegra20_ac97 *ac97 = dev_get_drvdata(&pdev->dev); 453 struct tegra20_ac97 *ac97 = dev_get_drvdata(&pdev->dev);
448 454
449 tegra_pcm_platform_unregister(&pdev->dev); 455 tegra_pcm_platform_unregister(&pdev->dev);
450 snd_soc_unregister_dai(&pdev->dev); 456 snd_soc_unregister_component(&pdev->dev);
451 457
452 tegra_asoc_utils_fini(&ac97->util_data); 458 tegra_asoc_utils_fini(&ac97->util_data);
453 459
diff --git a/sound/soc/tegra/tegra20_ac97.h b/sound/soc/tegra/tegra20_ac97.h
index dddc6828004e..4acb3aaba29b 100644
--- a/sound/soc/tegra/tegra20_ac97.h
+++ b/sound/soc/tegra/tegra20_ac97.h
@@ -85,8 +85,8 @@
85 85
86struct tegra20_ac97 { 86struct tegra20_ac97 {
87 struct clk *clk_ac97; 87 struct clk *clk_ac97;
88 struct tegra_pcm_dma_params capture_dma_data; 88 struct snd_dmaengine_dai_dma_data capture_dma_data;
89 struct tegra_pcm_dma_params playback_dma_data; 89 struct snd_dmaengine_dai_dma_data playback_dma_data;
90 struct regmap *regmap; 90 struct regmap *regmap;
91 int reset_gpio; 91 int reset_gpio;
92 int sync_gpio; 92 int sync_gpio;
diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c
index caa772de5a18..52af7f6fb37f 100644
--- a/sound/soc/tegra/tegra20_i2s.c
+++ b/sound/soc/tegra/tegra20_i2s.c
@@ -41,6 +41,7 @@
41#include <sound/pcm.h> 41#include <sound/pcm.h>
42#include <sound/pcm_params.h> 42#include <sound/pcm_params.h>
43#include <sound/soc.h> 43#include <sound/soc.h>
44#include <sound/dmaengine_pcm.h>
44 45
45#include "tegra20_i2s.h" 46#include "tegra20_i2s.h"
46 47
@@ -276,6 +277,10 @@ static const struct snd_soc_dai_driver tegra20_i2s_dai_template = {
276 .symmetric_rates = 1, 277 .symmetric_rates = 1,
277}; 278};
278 279
280static const struct snd_soc_component_driver tegra20_i2s_component = {
281 .name = DRV_NAME,
282};
283
279static bool tegra20_i2s_wr_rd_reg(struct device *dev, unsigned int reg) 284static bool tegra20_i2s_wr_rd_reg(struct device *dev, unsigned int reg)
280{ 285{
281 switch (reg) { 286 switch (reg) {
@@ -403,14 +408,14 @@ static int tegra20_i2s_platform_probe(struct platform_device *pdev)
403 } 408 }
404 409
405 i2s->capture_dma_data.addr = mem->start + TEGRA20_I2S_FIFO2; 410 i2s->capture_dma_data.addr = mem->start + TEGRA20_I2S_FIFO2;
406 i2s->capture_dma_data.wrap = 4; 411 i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
407 i2s->capture_dma_data.width = 32; 412 i2s->capture_dma_data.maxburst = 4;
408 i2s->capture_dma_data.req_sel = dma_ch; 413 i2s->capture_dma_data.slave_id = dma_ch;
409 414
410 i2s->playback_dma_data.addr = mem->start + TEGRA20_I2S_FIFO1; 415 i2s->playback_dma_data.addr = mem->start + TEGRA20_I2S_FIFO1;
411 i2s->playback_dma_data.wrap = 4; 416 i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
412 i2s->playback_dma_data.width = 32; 417 i2s->playback_dma_data.maxburst = 4;
413 i2s->playback_dma_data.req_sel = dma_ch; 418 i2s->playback_dma_data.slave_id = dma_ch;
414 419
415 pm_runtime_enable(&pdev->dev); 420 pm_runtime_enable(&pdev->dev);
416 if (!pm_runtime_enabled(&pdev->dev)) { 421 if (!pm_runtime_enabled(&pdev->dev)) {
@@ -419,7 +424,8 @@ static int tegra20_i2s_platform_probe(struct platform_device *pdev)
419 goto err_pm_disable; 424 goto err_pm_disable;
420 } 425 }
421 426
422 ret = snd_soc_register_dai(&pdev->dev, &i2s->dai); 427 ret = snd_soc_register_component(&pdev->dev, &tegra20_i2s_component,
428 &i2s->dai, 1);
423 if (ret) { 429 if (ret) {
424 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); 430 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
425 ret = -ENOMEM; 431 ret = -ENOMEM;
@@ -429,13 +435,13 @@ static int tegra20_i2s_platform_probe(struct platform_device *pdev)
429 ret = tegra_pcm_platform_register(&pdev->dev); 435 ret = tegra_pcm_platform_register(&pdev->dev);
430 if (ret) { 436 if (ret) {
431 dev_err(&pdev->dev, "Could not register PCM: %d\n", ret); 437 dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
432 goto err_unregister_dai; 438 goto err_unregister_component;
433 } 439 }
434 440
435 return 0; 441 return 0;
436 442
437err_unregister_dai: 443err_unregister_component:
438 snd_soc_unregister_dai(&pdev->dev); 444 snd_soc_unregister_component(&pdev->dev);
439err_suspend: 445err_suspend:
440 if (!pm_runtime_status_suspended(&pdev->dev)) 446 if (!pm_runtime_status_suspended(&pdev->dev))
441 tegra20_i2s_runtime_suspend(&pdev->dev); 447 tegra20_i2s_runtime_suspend(&pdev->dev);
@@ -456,7 +462,7 @@ static int tegra20_i2s_platform_remove(struct platform_device *pdev)
456 tegra20_i2s_runtime_suspend(&pdev->dev); 462 tegra20_i2s_runtime_suspend(&pdev->dev);
457 463
458 tegra_pcm_platform_unregister(&pdev->dev); 464 tegra_pcm_platform_unregister(&pdev->dev);
459 snd_soc_unregister_dai(&pdev->dev); 465 snd_soc_unregister_component(&pdev->dev);
460 466
461 clk_put(i2s->clk_i2s); 467 clk_put(i2s->clk_i2s);
462 468
diff --git a/sound/soc/tegra/tegra20_i2s.h b/sound/soc/tegra/tegra20_i2s.h
index 729958713cd4..fa6c29cc12b9 100644
--- a/sound/soc/tegra/tegra20_i2s.h
+++ b/sound/soc/tegra/tegra20_i2s.h
@@ -155,8 +155,8 @@
155struct tegra20_i2s { 155struct tegra20_i2s {
156 struct snd_soc_dai_driver dai; 156 struct snd_soc_dai_driver dai;
157 struct clk *clk_i2s; 157 struct clk *clk_i2s;
158 struct tegra_pcm_dma_params capture_dma_data; 158 struct snd_dmaengine_dai_dma_data capture_dma_data;
159 struct tegra_pcm_dma_params playback_dma_data; 159 struct snd_dmaengine_dai_dma_data playback_dma_data;
160 struct regmap *regmap; 160 struct regmap *regmap;
161}; 161};
162 162
diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c
index 04771d14d343..5eaa12cdc6eb 100644
--- a/sound/soc/tegra/tegra20_spdif.c
+++ b/sound/soc/tegra/tegra20_spdif.c
@@ -32,6 +32,7 @@
32#include <sound/pcm.h> 32#include <sound/pcm.h>
33#include <sound/pcm_params.h> 33#include <sound/pcm_params.h>
34#include <sound/soc.h> 34#include <sound/soc.h>
35#include <sound/dmaengine_pcm.h>
35 36
36#include "tegra20_spdif.h" 37#include "tegra20_spdif.h"
37 38
@@ -182,6 +183,10 @@ static struct snd_soc_dai_driver tegra20_spdif_dai = {
182 .ops = &tegra20_spdif_dai_ops, 183 .ops = &tegra20_spdif_dai_ops,
183}; 184};
184 185
186static const struct snd_soc_component_driver tegra20_spdif_component = {
187 .name = DRV_NAME,
188};
189
185static bool tegra20_spdif_wr_rd_reg(struct device *dev, unsigned int reg) 190static bool tegra20_spdif_wr_rd_reg(struct device *dev, unsigned int reg)
186{ 191{
187 switch (reg) { 192 switch (reg) {
@@ -318,9 +323,9 @@ static int tegra20_spdif_platform_probe(struct platform_device *pdev)
318 } 323 }
319 324
320 spdif->playback_dma_data.addr = mem->start + TEGRA20_SPDIF_DATA_OUT; 325 spdif->playback_dma_data.addr = mem->start + TEGRA20_SPDIF_DATA_OUT;
321 spdif->playback_dma_data.wrap = 4; 326 spdif->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
322 spdif->playback_dma_data.width = 32; 327 spdif->capture_dma_data.maxburst = 4;
323 spdif->playback_dma_data.req_sel = dmareq->start; 328 spdif->playback_dma_data.slave_id = dmareq->start;
324 329
325 pm_runtime_enable(&pdev->dev); 330 pm_runtime_enable(&pdev->dev);
326 if (!pm_runtime_enabled(&pdev->dev)) { 331 if (!pm_runtime_enabled(&pdev->dev)) {
@@ -329,7 +334,8 @@ static int tegra20_spdif_platform_probe(struct platform_device *pdev)
329 goto err_pm_disable; 334 goto err_pm_disable;
330 } 335 }
331 336
332 ret = snd_soc_register_dai(&pdev->dev, &tegra20_spdif_dai); 337 ret = snd_soc_register_component(&pdev->dev, &tegra20_spdif_component,
338 &tegra20_spdif_dai, 1);
333 if (ret) { 339 if (ret) {
334 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); 340 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
335 ret = -ENOMEM; 341 ret = -ENOMEM;
@@ -339,13 +345,13 @@ static int tegra20_spdif_platform_probe(struct platform_device *pdev)
339 ret = tegra_pcm_platform_register(&pdev->dev); 345 ret = tegra_pcm_platform_register(&pdev->dev);
340 if (ret) { 346 if (ret) {
341 dev_err(&pdev->dev, "Could not register PCM: %d\n", ret); 347 dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
342 goto err_unregister_dai; 348 goto err_unregister_component;
343 } 349 }
344 350
345 return 0; 351 return 0;
346 352
347err_unregister_dai: 353err_unregister_component:
348 snd_soc_unregister_dai(&pdev->dev); 354 snd_soc_unregister_component(&pdev->dev);
349err_suspend: 355err_suspend:
350 if (!pm_runtime_status_suspended(&pdev->dev)) 356 if (!pm_runtime_status_suspended(&pdev->dev))
351 tegra20_spdif_runtime_suspend(&pdev->dev); 357 tegra20_spdif_runtime_suspend(&pdev->dev);
@@ -366,7 +372,7 @@ static int tegra20_spdif_platform_remove(struct platform_device *pdev)
366 tegra20_spdif_runtime_suspend(&pdev->dev); 372 tegra20_spdif_runtime_suspend(&pdev->dev);
367 373
368 tegra_pcm_platform_unregister(&pdev->dev); 374 tegra_pcm_platform_unregister(&pdev->dev);
369 snd_soc_unregister_dai(&pdev->dev); 375 snd_soc_unregister_component(&pdev->dev);
370 376
371 clk_put(spdif->clk_spdif_out); 377 clk_put(spdif->clk_spdif_out);
372 378
diff --git a/sound/soc/tegra/tegra20_spdif.h b/sound/soc/tegra/tegra20_spdif.h
index b48d699fd583..85a9aefcc287 100644
--- a/sound/soc/tegra/tegra20_spdif.h
+++ b/sound/soc/tegra/tegra20_spdif.h
@@ -462,8 +462,8 @@
462 462
463struct tegra20_spdif { 463struct tegra20_spdif {
464 struct clk *clk_spdif_out; 464 struct clk *clk_spdif_out;
465 struct tegra_pcm_dma_params capture_dma_data; 465 struct snd_dmaengine_dai_dma_data capture_dma_data;
466 struct tegra_pcm_dma_params playback_dma_data; 466 struct snd_dmaengine_dai_dma_data playback_dma_data;
467 struct regmap *regmap; 467 struct regmap *regmap;
468}; 468};
469 469
diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c
index e5cfb4ac41ba..23e592f453fa 100644
--- a/sound/soc/tegra/tegra30_ahub.c
+++ b/sound/soc/tegra/tegra30_ahub.c
@@ -95,8 +95,8 @@ static int tegra30_ahub_runtime_resume(struct device *dev)
95} 95}
96 96
97int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif, 97int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif,
98 unsigned long *fiforeg, 98 dma_addr_t *fiforeg,
99 unsigned long *reqsel) 99 unsigned int *reqsel)
100{ 100{
101 int channel; 101 int channel;
102 u32 reg, val; 102 u32 reg, val;
@@ -178,8 +178,8 @@ int tegra30_ahub_free_rx_fifo(enum tegra30_ahub_rxcif rxcif)
178EXPORT_SYMBOL_GPL(tegra30_ahub_free_rx_fifo); 178EXPORT_SYMBOL_GPL(tegra30_ahub_free_rx_fifo);
179 179
180int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif, 180int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif,
181 unsigned long *fiforeg, 181 dma_addr_t *fiforeg,
182 unsigned long *reqsel) 182 unsigned int *reqsel)
183{ 183{
184 int channel; 184 int channel;
185 u32 reg, val; 185 u32 reg, val;
@@ -287,16 +287,27 @@ int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif)
287} 287}
288EXPORT_SYMBOL_GPL(tegra30_ahub_unset_rx_cif_source); 288EXPORT_SYMBOL_GPL(tegra30_ahub_unset_rx_cif_source);
289 289
290static const char * const configlink_clocks[] = { 290#define CLK_LIST_MASK_TEGRA30 BIT(0)
291 "i2s0", 291#define CLK_LIST_MASK_TEGRA114 BIT(1)
292 "i2s1", 292
293 "i2s2", 293#define CLK_LIST_MASK_TEGRA30_OR_LATER \
294 "i2s3", 294 (CLK_LIST_MASK_TEGRA30 | CLK_LIST_MASK_TEGRA114)
295 "i2s4", 295
296 "dam0", 296static const struct {
297 "dam1", 297 const char *clk_name;
298 "dam2", 298 u32 clk_list_mask;
299 "spdif_in", 299} configlink_clocks[] = {
300 { "i2s0", CLK_LIST_MASK_TEGRA30_OR_LATER },
301 { "i2s1", CLK_LIST_MASK_TEGRA30_OR_LATER },
302 { "i2s2", CLK_LIST_MASK_TEGRA30_OR_LATER },
303 { "i2s3", CLK_LIST_MASK_TEGRA30_OR_LATER },
304 { "i2s4", CLK_LIST_MASK_TEGRA30_OR_LATER },
305 { "dam0", CLK_LIST_MASK_TEGRA30_OR_LATER },
306 { "dam1", CLK_LIST_MASK_TEGRA30_OR_LATER },
307 { "dam2", CLK_LIST_MASK_TEGRA30_OR_LATER },
308 { "spdif_in", CLK_LIST_MASK_TEGRA30_OR_LATER },
309 { "amx", CLK_LIST_MASK_TEGRA114 },
310 { "adx", CLK_LIST_MASK_TEGRA114 },
300}; 311};
301 312
302#define LAST_REG(name) \ 313#define LAST_REG(name) \
@@ -424,8 +435,24 @@ static const struct regmap_config tegra30_ahub_ahub_regmap_config = {
424 .cache_type = REGCACHE_RBTREE, 435 .cache_type = REGCACHE_RBTREE,
425}; 436};
426 437
438static struct tegra30_ahub_soc_data soc_data_tegra30 = {
439 .clk_list_mask = CLK_LIST_MASK_TEGRA30,
440};
441
442static struct tegra30_ahub_soc_data soc_data_tegra114 = {
443 .clk_list_mask = CLK_LIST_MASK_TEGRA114,
444};
445
446static const struct of_device_id tegra30_ahub_of_match[] = {
447 { .compatible = "nvidia,tegra114-ahub", .data = &soc_data_tegra114 },
448 { .compatible = "nvidia,tegra30-ahub", .data = &soc_data_tegra30 },
449 {},
450};
451
427static int tegra30_ahub_probe(struct platform_device *pdev) 452static int tegra30_ahub_probe(struct platform_device *pdev)
428{ 453{
454 const struct of_device_id *match;
455 const struct tegra30_ahub_soc_data *soc_data;
429 struct clk *clk; 456 struct clk *clk;
430 int i; 457 int i;
431 struct resource *res0, *res1, *region; 458 struct resource *res0, *res1, *region;
@@ -436,16 +463,24 @@ static int tegra30_ahub_probe(struct platform_device *pdev)
436 if (ahub) 463 if (ahub)
437 return -ENODEV; 464 return -ENODEV;
438 465
466 match = of_match_device(tegra30_ahub_of_match, &pdev->dev);
467 if (!match)
468 return -EINVAL;
469 soc_data = match->data;
470
439 /* 471 /*
440 * The AHUB hosts a register bus: the "configlink". For this to 472 * The AHUB hosts a register bus: the "configlink". For this to
441 * operate correctly, all devices on this bus must be out of reset. 473 * operate correctly, all devices on this bus must be out of reset.
442 * Ensure that here. 474 * Ensure that here.
443 */ 475 */
444 for (i = 0; i < ARRAY_SIZE(configlink_clocks); i++) { 476 for (i = 0; i < ARRAY_SIZE(configlink_clocks); i++) {
445 clk = clk_get(&pdev->dev, configlink_clocks[i]); 477 if (!(configlink_clocks[i].clk_list_mask &
478 soc_data->clk_list_mask))
479 continue;
480 clk = clk_get(&pdev->dev, configlink_clocks[i].clk_name);
446 if (IS_ERR(clk)) { 481 if (IS_ERR(clk)) {
447 dev_err(&pdev->dev, "Can't get clock %s\n", 482 dev_err(&pdev->dev, "Can't get clock %s\n",
448 configlink_clocks[i]); 483 configlink_clocks[i].clk_name);
449 ret = PTR_ERR(clk); 484 ret = PTR_ERR(clk);
450 goto err; 485 goto err;
451 } 486 }
@@ -592,11 +627,6 @@ static int tegra30_ahub_remove(struct platform_device *pdev)
592 return 0; 627 return 0;
593} 628}
594 629
595static const struct of_device_id tegra30_ahub_of_match[] = {
596 { .compatible = "nvidia,tegra30-ahub", },
597 {},
598};
599
600static const struct dev_pm_ops tegra30_ahub_pm_ops = { 630static const struct dev_pm_ops tegra30_ahub_pm_ops = {
601 SET_RUNTIME_PM_OPS(tegra30_ahub_runtime_suspend, 631 SET_RUNTIME_PM_OPS(tegra30_ahub_runtime_suspend,
602 tegra30_ahub_runtime_resume, NULL) 632 tegra30_ahub_runtime_resume, NULL)
diff --git a/sound/soc/tegra/tegra30_ahub.h b/sound/soc/tegra/tegra30_ahub.h
index e690e2eecc92..09766cdc45ca 100644
--- a/sound/soc/tegra/tegra30_ahub.h
+++ b/sound/soc/tegra/tegra30_ahub.h
@@ -451,15 +451,15 @@ enum tegra30_ahub_rxcif {
451}; 451};
452 452
453extern int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif, 453extern int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif,
454 unsigned long *fiforeg, 454 dma_addr_t *fiforeg,
455 unsigned long *reqsel); 455 unsigned int *reqsel);
456extern int tegra30_ahub_enable_rx_fifo(enum tegra30_ahub_rxcif rxcif); 456extern int tegra30_ahub_enable_rx_fifo(enum tegra30_ahub_rxcif rxcif);
457extern int tegra30_ahub_disable_rx_fifo(enum tegra30_ahub_rxcif rxcif); 457extern int tegra30_ahub_disable_rx_fifo(enum tegra30_ahub_rxcif rxcif);
458extern int tegra30_ahub_free_rx_fifo(enum tegra30_ahub_rxcif rxcif); 458extern int tegra30_ahub_free_rx_fifo(enum tegra30_ahub_rxcif rxcif);
459 459
460extern int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif, 460extern int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif,
461 unsigned long *fiforeg, 461 dma_addr_t *fiforeg,
462 unsigned long *reqsel); 462 unsigned int *reqsel);
463extern int tegra30_ahub_enable_tx_fifo(enum tegra30_ahub_txcif txcif); 463extern int tegra30_ahub_enable_tx_fifo(enum tegra30_ahub_txcif txcif);
464extern int tegra30_ahub_disable_tx_fifo(enum tegra30_ahub_txcif txcif); 464extern int tegra30_ahub_disable_tx_fifo(enum tegra30_ahub_txcif txcif);
465extern int tegra30_ahub_free_tx_fifo(enum tegra30_ahub_txcif txcif); 465extern int tegra30_ahub_free_tx_fifo(enum tegra30_ahub_txcif txcif);
@@ -468,7 +468,23 @@ extern int tegra30_ahub_set_rx_cif_source(enum tegra30_ahub_rxcif rxcif,
468 enum tegra30_ahub_txcif txcif); 468 enum tegra30_ahub_txcif txcif);
469extern int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif); 469extern int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif);
470 470
471struct tegra30_ahub_soc_data {
472 u32 clk_list_mask;
473 /*
474 * FIXME: There are many more differences in HW, such as:
475 * - More APBIF channels.
476 * - Extra separate chunks of register address space to represent
477 * the extra APBIF channels.
478 * - More units connected to the AHUB, so that tegra30_ahub_[rt]xcif
479 * need expansion, coupled with there being more defined bits in
480 * the AHUB routing registers.
481 * However, the driver doesn't support those new features yet, so we
482 * don't represent them here yet.
483 */
484};
485
471struct tegra30_ahub { 486struct tegra30_ahub {
487 const struct tegra30_ahub_soc_data *soc_data;
472 struct device *dev; 488 struct device *dev;
473 struct clk *clk_d_audio; 489 struct clk *clk_d_audio;
474 struct clk *clk_apbif; 490 struct clk *clk_apbif;
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c
index f4e1ce82750a..31d092d83c71 100644
--- a/sound/soc/tegra/tegra30_i2s.c
+++ b/sound/soc/tegra/tegra30_i2s.c
@@ -38,6 +38,7 @@
38#include <sound/pcm.h> 38#include <sound/pcm.h>
39#include <sound/pcm_params.h> 39#include <sound/pcm_params.h>
40#include <sound/soc.h> 40#include <sound/soc.h>
41#include <sound/dmaengine_pcm.h>
41 42
42#include "tegra30_ahub.h" 43#include "tegra30_ahub.h"
43#include "tegra30_i2s.h" 44#include "tegra30_i2s.h"
@@ -80,17 +81,17 @@ static int tegra30_i2s_startup(struct snd_pcm_substream *substream,
80 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 81 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
81 ret = tegra30_ahub_allocate_tx_fifo(&i2s->playback_fifo_cif, 82 ret = tegra30_ahub_allocate_tx_fifo(&i2s->playback_fifo_cif,
82 &i2s->playback_dma_data.addr, 83 &i2s->playback_dma_data.addr,
83 &i2s->playback_dma_data.req_sel); 84 &i2s->playback_dma_data.slave_id);
84 i2s->playback_dma_data.wrap = 4; 85 i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
85 i2s->playback_dma_data.width = 32; 86 i2s->playback_dma_data.maxburst = 4;
86 tegra30_ahub_set_rx_cif_source(i2s->playback_i2s_cif, 87 tegra30_ahub_set_rx_cif_source(i2s->playback_i2s_cif,
87 i2s->playback_fifo_cif); 88 i2s->playback_fifo_cif);
88 } else { 89 } else {
89 ret = tegra30_ahub_allocate_rx_fifo(&i2s->capture_fifo_cif, 90 ret = tegra30_ahub_allocate_rx_fifo(&i2s->capture_fifo_cif,
90 &i2s->capture_dma_data.addr, 91 &i2s->capture_dma_data.addr,
91 &i2s->capture_dma_data.req_sel); 92 &i2s->capture_dma_data.slave_id);
92 i2s->capture_dma_data.wrap = 4; 93 i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
93 i2s->capture_dma_data.width = 32; 94 i2s->capture_dma_data.maxburst = 4;
94 tegra30_ahub_set_rx_cif_source(i2s->capture_fifo_cif, 95 tegra30_ahub_set_rx_cif_source(i2s->capture_fifo_cif,
95 i2s->capture_i2s_cif); 96 i2s->capture_i2s_cif);
96 } 97 }
@@ -336,6 +337,10 @@ static const struct snd_soc_dai_driver tegra30_i2s_dai_template = {
336 .symmetric_rates = 1, 337 .symmetric_rates = 1,
337}; 338};
338 339
340static const struct snd_soc_component_driver tegra30_i2s_component = {
341 .name = DRV_NAME,
342};
343
339static bool tegra30_i2s_wr_rd_reg(struct device *dev, unsigned int reg) 344static bool tegra30_i2s_wr_rd_reg(struct device *dev, unsigned int reg)
340{ 345{
341 switch (reg) { 346 switch (reg) {
@@ -464,7 +469,8 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev)
464 goto err_pm_disable; 469 goto err_pm_disable;
465 } 470 }
466 471
467 ret = snd_soc_register_dai(&pdev->dev, &i2s->dai); 472 ret = snd_soc_register_component(&pdev->dev, &tegra30_i2s_component,
473 &i2s->dai, 1);
468 if (ret) { 474 if (ret) {
469 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); 475 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
470 ret = -ENOMEM; 476 ret = -ENOMEM;
@@ -474,13 +480,13 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev)
474 ret = tegra_pcm_platform_register(&pdev->dev); 480 ret = tegra_pcm_platform_register(&pdev->dev);
475 if (ret) { 481 if (ret) {
476 dev_err(&pdev->dev, "Could not register PCM: %d\n", ret); 482 dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
477 goto err_unregister_dai; 483 goto err_unregister_component;
478 } 484 }
479 485
480 return 0; 486 return 0;
481 487
482err_unregister_dai: 488err_unregister_component:
483 snd_soc_unregister_dai(&pdev->dev); 489 snd_soc_unregister_component(&pdev->dev);
484err_suspend: 490err_suspend:
485 if (!pm_runtime_status_suspended(&pdev->dev)) 491 if (!pm_runtime_status_suspended(&pdev->dev))
486 tegra30_i2s_runtime_suspend(&pdev->dev); 492 tegra30_i2s_runtime_suspend(&pdev->dev);
@@ -501,7 +507,7 @@ static int tegra30_i2s_platform_remove(struct platform_device *pdev)
501 tegra30_i2s_runtime_suspend(&pdev->dev); 507 tegra30_i2s_runtime_suspend(&pdev->dev);
502 508
503 tegra_pcm_platform_unregister(&pdev->dev); 509 tegra_pcm_platform_unregister(&pdev->dev);
504 snd_soc_unregister_dai(&pdev->dev); 510 snd_soc_unregister_component(&pdev->dev);
505 511
506 clk_put(i2s->clk_i2s); 512 clk_put(i2s->clk_i2s);
507 513
diff --git a/sound/soc/tegra/tegra30_i2s.h b/sound/soc/tegra/tegra30_i2s.h
index a294d942b9f7..bea23afe3b9f 100644
--- a/sound/soc/tegra/tegra30_i2s.h
+++ b/sound/soc/tegra/tegra30_i2s.h
@@ -231,10 +231,10 @@ struct tegra30_i2s {
231 struct clk *clk_i2s; 231 struct clk *clk_i2s;
232 enum tegra30_ahub_txcif capture_i2s_cif; 232 enum tegra30_ahub_txcif capture_i2s_cif;
233 enum tegra30_ahub_rxcif capture_fifo_cif; 233 enum tegra30_ahub_rxcif capture_fifo_cif;
234 struct tegra_pcm_dma_params capture_dma_data; 234 struct snd_dmaengine_dai_dma_data capture_dma_data;
235 enum tegra30_ahub_rxcif playback_i2s_cif; 235 enum tegra30_ahub_rxcif playback_i2s_cif;
236 enum tegra30_ahub_txcif playback_fifo_cif; 236 enum tegra30_ahub_txcif playback_fifo_cif;
237 struct tegra_pcm_dma_params playback_dma_data; 237 struct snd_dmaengine_dai_dma_data playback_dma_data;
238 struct regmap *regmap; 238 struct regmap *regmap;
239}; 239};
240 240
diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c
index c80adb9da472..48d05d9e1002 100644
--- a/sound/soc/tegra/tegra_alc5632.c
+++ b/sound/soc/tegra/tegra_alc5632.c
@@ -161,20 +161,13 @@ static int tegra_alc5632_probe(struct platform_device *pdev)
161 sizeof(struct tegra_alc5632), GFP_KERNEL); 161 sizeof(struct tegra_alc5632), GFP_KERNEL);
162 if (!alc5632) { 162 if (!alc5632) {
163 dev_err(&pdev->dev, "Can't allocate tegra_alc5632\n"); 163 dev_err(&pdev->dev, "Can't allocate tegra_alc5632\n");
164 ret = -ENOMEM; 164 return -ENOMEM;
165 goto err;
166 } 165 }
167 166
168 card->dev = &pdev->dev; 167 card->dev = &pdev->dev;
169 platform_set_drvdata(pdev, card); 168 platform_set_drvdata(pdev, card);
170 snd_soc_card_set_drvdata(card, alc5632); 169 snd_soc_card_set_drvdata(card, alc5632);
171 170
172 if (!(pdev->dev.of_node)) {
173 dev_err(&pdev->dev, "Must be instantiated using device tree\n");
174 ret = -EINVAL;
175 goto err;
176 }
177
178 alc5632->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0); 171 alc5632->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0);
179 if (alc5632->gpio_hp_det == -EPROBE_DEFER) 172 if (alc5632->gpio_hp_det == -EPROBE_DEFER)
180 return -EPROBE_DEFER; 173 return -EPROBE_DEFER;
@@ -197,11 +190,11 @@ static int tegra_alc5632_probe(struct platform_device *pdev)
197 goto err; 190 goto err;
198 } 191 }
199 192
200 tegra_alc5632_dai.cpu_of_node = of_parse_phandle( 193 tegra_alc5632_dai.cpu_of_node = of_parse_phandle(np,
201 pdev->dev.of_node, "nvidia,i2s-controller", 0); 194 "nvidia,i2s-controller", 0);
202 if (!tegra_alc5632_dai.cpu_of_node) { 195 if (!tegra_alc5632_dai.cpu_of_node) {
203 dev_err(&pdev->dev, 196 dev_err(&pdev->dev,
204 "Property 'nvidia,i2s-controller' missing or invalid\n"); 197 "Property 'nvidia,i2s-controller' missing or invalid\n");
205 ret = -EINVAL; 198 ret = -EINVAL;
206 goto err; 199 goto err;
207 } 200 }
diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c
index ba419f86384d..24fb001be7f4 100644
--- a/sound/soc/tegra/tegra_asoc_utils.c
+++ b/sound/soc/tegra/tegra_asoc_utils.c
@@ -43,8 +43,10 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
43 case 88200: 43 case 88200:
44 if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA20) 44 if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA20)
45 new_baseclock = 56448000; 45 new_baseclock = 56448000;
46 else 46 else if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA30)
47 new_baseclock = 564480000; 47 new_baseclock = 564480000;
48 else
49 new_baseclock = 282240000;
48 break; 50 break;
49 case 8000: 51 case 8000:
50 case 16000: 52 case 16000:
@@ -54,8 +56,10 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
54 case 96000: 56 case 96000:
55 if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA20) 57 if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA20)
56 new_baseclock = 73728000; 58 new_baseclock = 73728000;
57 else 59 else if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA30)
58 new_baseclock = 552960000; 60 new_baseclock = 552960000;
61 else
62 new_baseclock = 368640000;
59 break; 63 break;
60 default: 64 default:
61 return -EINVAL; 65 return -EINVAL;
@@ -169,6 +173,7 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
169 struct device *dev) 173 struct device *dev)
170{ 174{
171 int ret; 175 int ret;
176 bool new_clocks = false;
172 177
173 data->dev = dev; 178 data->dev = dev;
174 179
@@ -176,28 +181,37 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
176 data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA20; 181 data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA20;
177 else if (of_machine_is_compatible("nvidia,tegra30")) 182 else if (of_machine_is_compatible("nvidia,tegra30"))
178 data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA30; 183 data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA30;
179 else if (!dev->of_node) 184 else if (of_machine_is_compatible("nvidia,tegra114")) {
180 /* non-DT is always Tegra20 */ 185 data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA114;
181 data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA20; 186 new_clocks = true;
182 else 187 } else {
183 /* DT boot, but unknown SoC */ 188 dev_err(data->dev, "SoC unknown to Tegra ASoC utils\n");
184 return -EINVAL; 189 return -EINVAL;
190 }
185 191
186 data->clk_pll_a = clk_get_sys(NULL, "pll_a"); 192 if (new_clocks)
193 data->clk_pll_a = clk_get(dev, "pll_a");
194 else
195 data->clk_pll_a = clk_get_sys(NULL, "pll_a");
187 if (IS_ERR(data->clk_pll_a)) { 196 if (IS_ERR(data->clk_pll_a)) {
188 dev_err(data->dev, "Can't retrieve clk pll_a\n"); 197 dev_err(data->dev, "Can't retrieve clk pll_a\n");
189 ret = PTR_ERR(data->clk_pll_a); 198 ret = PTR_ERR(data->clk_pll_a);
190 goto err; 199 goto err;
191 } 200 }
192 201
193 data->clk_pll_a_out0 = clk_get_sys(NULL, "pll_a_out0"); 202 if (new_clocks)
203 data->clk_pll_a_out0 = clk_get(dev, "pll_a_out0");
204 else
205 data->clk_pll_a_out0 = clk_get_sys(NULL, "pll_a_out0");
194 if (IS_ERR(data->clk_pll_a_out0)) { 206 if (IS_ERR(data->clk_pll_a_out0)) {
195 dev_err(data->dev, "Can't retrieve clk pll_a_out0\n"); 207 dev_err(data->dev, "Can't retrieve clk pll_a_out0\n");
196 ret = PTR_ERR(data->clk_pll_a_out0); 208 ret = PTR_ERR(data->clk_pll_a_out0);
197 goto err_put_pll_a; 209 goto err_put_pll_a;
198 } 210 }
199 211
200 if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA20) 212 if (new_clocks)
213 data->clk_cdev1 = clk_get(dev, "mclk");
214 else if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA20)
201 data->clk_cdev1 = clk_get_sys(NULL, "cdev1"); 215 data->clk_cdev1 = clk_get_sys(NULL, "cdev1");
202 else 216 else
203 data->clk_cdev1 = clk_get_sys("extern1", NULL); 217 data->clk_cdev1 = clk_get_sys("extern1", NULL);
diff --git a/sound/soc/tegra/tegra_asoc_utils.h b/sound/soc/tegra/tegra_asoc_utils.h
index 974c9f8830f9..19fdcafed32f 100644
--- a/sound/soc/tegra/tegra_asoc_utils.h
+++ b/sound/soc/tegra/tegra_asoc_utils.h
@@ -29,6 +29,7 @@ struct device;
29enum tegra_asoc_utils_soc { 29enum tegra_asoc_utils_soc {
30 TEGRA_ASOC_UTILS_SOC_TEGRA20, 30 TEGRA_ASOC_UTILS_SOC_TEGRA20,
31 TEGRA_ASOC_UTILS_SOC_TEGRA30, 31 TEGRA_ASOC_UTILS_SOC_TEGRA30,
32 TEGRA_ASOC_UTILS_SOC_TEGRA114,
32}; 33};
33 34
34struct tegra_asoc_utils_data { 35struct tegra_asoc_utils_data {
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index 5e2c55c5b255..f056f632557c 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -29,9 +29,7 @@
29 * 29 *
30 */ 30 */
31 31
32#include <linux/dma-mapping.h>
33#include <linux/module.h> 32#include <linux/module.h>
34#include <linux/slab.h>
35#include <sound/core.h> 33#include <sound/core.h>
36#include <sound/pcm.h> 34#include <sound/pcm.h>
37#include <sound/pcm_params.h> 35#include <sound/pcm_params.h>
@@ -55,191 +53,24 @@ static const struct snd_pcm_hardware tegra_pcm_hardware = {
55 .fifo_size = 4, 53 .fifo_size = 4,
56}; 54};
57 55
58static int tegra_pcm_open(struct snd_pcm_substream *substream) 56static const struct snd_dmaengine_pcm_config tegra_dmaengine_pcm_config = {
59{ 57 .pcm_hardware = &tegra_pcm_hardware,
60 struct snd_soc_pcm_runtime *rtd = substream->private_data; 58 .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
61 struct device *dev = rtd->platform->dev; 59 .compat_filter_fn = NULL,
62 int ret; 60 .prealloc_buffer_size = PAGE_SIZE * 8,
63
64 /* Set HW params now that initialization is complete */
65 snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware);
66
67 ret = snd_dmaengine_pcm_open(substream, NULL, NULL);
68 if (ret) {
69 dev_err(dev, "dmaengine pcm open failed with err %d\n", ret);
70 return ret;
71 }
72
73 return 0;
74}
75
76static int tegra_pcm_close(struct snd_pcm_substream *substream)
77{
78 snd_dmaengine_pcm_close(substream);
79 return 0;
80}
81
82static int tegra_pcm_hw_params(struct snd_pcm_substream *substream,
83 struct snd_pcm_hw_params *params)
84{
85 struct snd_soc_pcm_runtime *rtd = substream->private_data;
86 struct device *dev = rtd->platform->dev;
87 struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
88 struct tegra_pcm_dma_params *dmap;
89 struct dma_slave_config slave_config;
90 int ret;
91
92 dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
93
94 ret = snd_hwparams_to_dma_slave_config(substream, params,
95 &slave_config);
96 if (ret) {
97 dev_err(dev, "hw params config failed with err %d\n", ret);
98 return ret;
99 }
100
101 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
102 slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
103 slave_config.dst_addr = dmap->addr;
104 slave_config.dst_maxburst = 4;
105 } else {
106 slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
107 slave_config.src_addr = dmap->addr;
108 slave_config.src_maxburst = 4;
109 }
110 slave_config.slave_id = dmap->req_sel;
111
112 ret = dmaengine_slave_config(chan, &slave_config);
113 if (ret < 0) {
114 dev_err(dev, "dma slave config failed with err %d\n", ret);
115 return ret;
116 }
117
118 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
119 return 0;
120}
121
122static int tegra_pcm_hw_free(struct snd_pcm_substream *substream)
123{
124 snd_pcm_set_runtime_buffer(substream, NULL);
125 return 0;
126}
127
128static int tegra_pcm_mmap(struct snd_pcm_substream *substream,
129 struct vm_area_struct *vma)
130{
131 struct snd_pcm_runtime *runtime = substream->runtime;
132
133 return dma_mmap_writecombine(substream->pcm->card->dev, vma,
134 runtime->dma_area,
135 runtime->dma_addr,
136 runtime->dma_bytes);
137}
138
139static struct snd_pcm_ops tegra_pcm_ops = {
140 .open = tegra_pcm_open,
141 .close = tegra_pcm_close,
142 .ioctl = snd_pcm_lib_ioctl,
143 .hw_params = tegra_pcm_hw_params,
144 .hw_free = tegra_pcm_hw_free,
145 .trigger = snd_dmaengine_pcm_trigger,
146 .pointer = snd_dmaengine_pcm_pointer,
147 .mmap = tegra_pcm_mmap,
148};
149
150static int tegra_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
151{
152 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
153 struct snd_dma_buffer *buf = &substream->dma_buffer;
154 size_t size = tegra_pcm_hardware.buffer_bytes_max;
155
156 buf->area = dma_alloc_writecombine(pcm->card->dev, size,
157 &buf->addr, GFP_KERNEL);
158 if (!buf->area)
159 return -ENOMEM;
160
161 buf->dev.type = SNDRV_DMA_TYPE_DEV;
162 buf->dev.dev = pcm->card->dev;
163 buf->private_data = NULL;
164 buf->bytes = size;
165
166 return 0;
167}
168
169static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream)
170{
171 struct snd_pcm_substream *substream;
172 struct snd_dma_buffer *buf;
173
174 substream = pcm->streams[stream].substream;
175 if (!substream)
176 return;
177
178 buf = &substream->dma_buffer;
179 if (!buf->area)
180 return;
181
182 dma_free_writecombine(pcm->card->dev, buf->bytes,
183 buf->area, buf->addr);
184 buf->area = NULL;
185}
186
187static u64 tegra_dma_mask = DMA_BIT_MASK(32);
188
189static int tegra_pcm_new(struct snd_soc_pcm_runtime *rtd)
190{
191 struct snd_card *card = rtd->card->snd_card;
192 struct snd_pcm *pcm = rtd->pcm;
193 int ret = 0;
194
195 if (!card->dev->dma_mask)
196 card->dev->dma_mask = &tegra_dma_mask;
197 if (!card->dev->coherent_dma_mask)
198 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
199
200 if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
201 ret = tegra_pcm_preallocate_dma_buffer(pcm,
202 SNDRV_PCM_STREAM_PLAYBACK);
203 if (ret)
204 goto err;
205 }
206
207 if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
208 ret = tegra_pcm_preallocate_dma_buffer(pcm,
209 SNDRV_PCM_STREAM_CAPTURE);
210 if (ret)
211 goto err_free_play;
212 }
213
214 return 0;
215
216err_free_play:
217 tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
218err:
219 return ret;
220}
221
222static void tegra_pcm_free(struct snd_pcm *pcm)
223{
224 tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE);
225 tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
226}
227
228static struct snd_soc_platform_driver tegra_pcm_platform = {
229 .ops = &tegra_pcm_ops,
230 .pcm_new = tegra_pcm_new,
231 .pcm_free = tegra_pcm_free,
232}; 61};
233 62
234int tegra_pcm_platform_register(struct device *dev) 63int tegra_pcm_platform_register(struct device *dev)
235{ 64{
236 return snd_soc_register_platform(dev, &tegra_pcm_platform); 65 return snd_dmaengine_pcm_register(dev, &tegra_dmaengine_pcm_config,
66 SND_DMAENGINE_PCM_FLAG_NO_DT |
67 SND_DMAENGINE_PCM_FLAG_COMPAT);
237} 68}
238EXPORT_SYMBOL_GPL(tegra_pcm_platform_register); 69EXPORT_SYMBOL_GPL(tegra_pcm_platform_register);
239 70
240void tegra_pcm_platform_unregister(struct device *dev) 71void tegra_pcm_platform_unregister(struct device *dev)
241{ 72{
242 snd_soc_unregister_platform(dev); 73 return snd_dmaengine_pcm_unregister(dev);
243} 74}
244EXPORT_SYMBOL_GPL(tegra_pcm_platform_unregister); 75EXPORT_SYMBOL_GPL(tegra_pcm_platform_unregister);
245 76
diff --git a/sound/soc/tegra/tegra_pcm.h b/sound/soc/tegra/tegra_pcm.h
index bc8b46af928e..68ad901714a9 100644
--- a/sound/soc/tegra/tegra_pcm.h
+++ b/sound/soc/tegra/tegra_pcm.h
@@ -31,13 +31,6 @@
31#ifndef __TEGRA_PCM_H__ 31#ifndef __TEGRA_PCM_H__
32#define __TEGRA_PCM_H__ 32#define __TEGRA_PCM_H__
33 33
34struct tegra_pcm_dma_params {
35 unsigned long addr;
36 unsigned long wrap;
37 unsigned long width;
38 unsigned long req_sel;
39};
40
41int tegra_pcm_platform_register(struct device *dev); 34int tegra_pcm_platform_register(struct device *dev);
42void tegra_pcm_platform_unregister(struct device *dev); 35void tegra_pcm_platform_unregister(struct device *dev);
43 36
diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c
index c8ef88a67c59..f87fc53e9b8c 100644
--- a/sound/soc/tegra/tegra_wm8753.c
+++ b/sound/soc/tegra/tegra_wm8753.c
@@ -124,6 +124,7 @@ static struct snd_soc_card snd_soc_tegra_wm8753 = {
124 124
125static int tegra_wm8753_driver_probe(struct platform_device *pdev) 125static int tegra_wm8753_driver_probe(struct platform_device *pdev)
126{ 126{
127 struct device_node *np = pdev->dev.of_node;
127 struct snd_soc_card *card = &snd_soc_tegra_wm8753; 128 struct snd_soc_card *card = &snd_soc_tegra_wm8753;
128 struct tegra_wm8753 *machine; 129 struct tegra_wm8753 *machine;
129 int ret; 130 int ret;
@@ -132,8 +133,7 @@ static int tegra_wm8753_driver_probe(struct platform_device *pdev)
132 GFP_KERNEL); 133 GFP_KERNEL);
133 if (!machine) { 134 if (!machine) {
134 dev_err(&pdev->dev, "Can't allocate tegra_wm8753 struct\n"); 135 dev_err(&pdev->dev, "Can't allocate tegra_wm8753 struct\n");
135 ret = -ENOMEM; 136 return -ENOMEM;
136 goto err;
137 } 137 }
138 138
139 card->dev = &pdev->dev; 139 card->dev = &pdev->dev;
@@ -148,8 +148,8 @@ static int tegra_wm8753_driver_probe(struct platform_device *pdev)
148 if (ret) 148 if (ret)
149 goto err; 149 goto err;
150 150
151 tegra_wm8753_dai.codec_of_node = of_parse_phandle( 151 tegra_wm8753_dai.codec_of_node = of_parse_phandle(np,
152 pdev->dev.of_node, "nvidia,audio-codec", 0); 152 "nvidia,audio-codec", 0);
153 if (!tegra_wm8753_dai.codec_of_node) { 153 if (!tegra_wm8753_dai.codec_of_node) {
154 dev_err(&pdev->dev, 154 dev_err(&pdev->dev,
155 "Property 'nvidia,audio-codec' missing or invalid\n"); 155 "Property 'nvidia,audio-codec' missing or invalid\n");
@@ -157,8 +157,8 @@ static int tegra_wm8753_driver_probe(struct platform_device *pdev)
157 goto err; 157 goto err;
158 } 158 }
159 159
160 tegra_wm8753_dai.cpu_of_node = of_parse_phandle( 160 tegra_wm8753_dai.cpu_of_node = of_parse_phandle(np,
161 pdev->dev.of_node, "nvidia,i2s-controller", 0); 161 "nvidia,i2s-controller", 0);
162 if (!tegra_wm8753_dai.cpu_of_node) { 162 if (!tegra_wm8753_dai.cpu_of_node) {
163 dev_err(&pdev->dev, 163 dev_err(&pdev->dev,
164 "Property 'nvidia,i2s-controller' missing or invalid\n"); 164 "Property 'nvidia,i2s-controller' missing or invalid\n");
@@ -166,8 +166,7 @@ static int tegra_wm8753_driver_probe(struct platform_device *pdev)
166 goto err; 166 goto err;
167 } 167 }
168 168
169 tegra_wm8753_dai.platform_of_node = 169 tegra_wm8753_dai.platform_of_node = tegra_wm8753_dai.cpu_of_node;
170 tegra_wm8753_dai.cpu_of_node;
171 170
172 ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); 171 ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
173 if (ret) 172 if (ret)
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c
index bbd79bf56303..4ac73730d79a 100644
--- a/sound/soc/tegra/tegra_wm8903.c
+++ b/sound/soc/tegra/tegra_wm8903.c
@@ -39,7 +39,6 @@
39#include <sound/pcm.h> 39#include <sound/pcm.h>
40#include <sound/pcm_params.h> 40#include <sound/pcm_params.h>
41#include <sound/soc.h> 41#include <sound/soc.h>
42#include <sound/tegra_wm8903.h>
43 42
44#include "../codecs/wm8903.h" 43#include "../codecs/wm8903.h"
45 44
@@ -48,7 +47,11 @@
48#define DRV_NAME "tegra-snd-wm8903" 47#define DRV_NAME "tegra-snd-wm8903"
49 48
50struct tegra_wm8903 { 49struct tegra_wm8903 {
51 struct tegra_wm8903_platform_data pdata; 50 int gpio_spkr_en;
51 int gpio_hp_det;
52 int gpio_hp_mute;
53 int gpio_int_mic_en;
54 int gpio_ext_mic_en;
52 struct tegra_asoc_utils_data util_data; 55 struct tegra_asoc_utils_data util_data;
53}; 56};
54 57
@@ -129,12 +132,11 @@ static int tegra_wm8903_event_int_spk(struct snd_soc_dapm_widget *w,
129 struct snd_soc_dapm_context *dapm = w->dapm; 132 struct snd_soc_dapm_context *dapm = w->dapm;
130 struct snd_soc_card *card = dapm->card; 133 struct snd_soc_card *card = dapm->card;
131 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); 134 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
132 struct tegra_wm8903_platform_data *pdata = &machine->pdata;
133 135
134 if (!gpio_is_valid(pdata->gpio_spkr_en)) 136 if (!gpio_is_valid(machine->gpio_spkr_en))
135 return 0; 137 return 0;
136 138
137 gpio_set_value_cansleep(pdata->gpio_spkr_en, 139 gpio_set_value_cansleep(machine->gpio_spkr_en,
138 SND_SOC_DAPM_EVENT_ON(event)); 140 SND_SOC_DAPM_EVENT_ON(event));
139 141
140 return 0; 142 return 0;
@@ -146,12 +148,11 @@ static int tegra_wm8903_event_hp(struct snd_soc_dapm_widget *w,
146 struct snd_soc_dapm_context *dapm = w->dapm; 148 struct snd_soc_dapm_context *dapm = w->dapm;
147 struct snd_soc_card *card = dapm->card; 149 struct snd_soc_card *card = dapm->card;
148 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); 150 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
149 struct tegra_wm8903_platform_data *pdata = &machine->pdata;
150 151
151 if (!gpio_is_valid(pdata->gpio_hp_mute)) 152 if (!gpio_is_valid(machine->gpio_hp_mute))
152 return 0; 153 return 0;
153 154
154 gpio_set_value_cansleep(pdata->gpio_hp_mute, 155 gpio_set_value_cansleep(machine->gpio_hp_mute,
155 !SND_SOC_DAPM_EVENT_ON(event)); 156 !SND_SOC_DAPM_EVENT_ON(event));
156 157
157 return 0; 158 return 0;
@@ -163,17 +164,6 @@ static const struct snd_soc_dapm_widget tegra_wm8903_dapm_widgets[] = {
163 SND_SOC_DAPM_MIC("Mic Jack", NULL), 164 SND_SOC_DAPM_MIC("Mic Jack", NULL),
164}; 165};
165 166
166static const struct snd_soc_dapm_route harmony_audio_map[] = {
167 {"Headphone Jack", NULL, "HPOUTR"},
168 {"Headphone Jack", NULL, "HPOUTL"},
169 {"Int Spk", NULL, "ROP"},
170 {"Int Spk", NULL, "RON"},
171 {"Int Spk", NULL, "LOP"},
172 {"Int Spk", NULL, "LON"},
173 {"Mic Jack", NULL, "MICBIAS"},
174 {"IN1L", NULL, "Mic Jack"},
175};
176
177static const struct snd_kcontrol_new tegra_wm8903_controls[] = { 167static const struct snd_kcontrol_new tegra_wm8903_controls[] = {
178 SOC_DAPM_PIN_SWITCH("Int Spk"), 168 SOC_DAPM_PIN_SWITCH("Int Spk"),
179}; 169};
@@ -185,10 +175,9 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
185 struct snd_soc_dapm_context *dapm = &codec->dapm; 175 struct snd_soc_dapm_context *dapm = &codec->dapm;
186 struct snd_soc_card *card = codec->card; 176 struct snd_soc_card *card = codec->card;
187 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); 177 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
188 struct tegra_wm8903_platform_data *pdata = &machine->pdata;
189 178
190 if (gpio_is_valid(pdata->gpio_hp_det)) { 179 if (gpio_is_valid(machine->gpio_hp_det)) {
191 tegra_wm8903_hp_jack_gpio.gpio = pdata->gpio_hp_det; 180 tegra_wm8903_hp_jack_gpio.gpio = machine->gpio_hp_det;
192 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE, 181 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
193 &tegra_wm8903_hp_jack); 182 &tegra_wm8903_hp_jack);
194 snd_soc_jack_add_pins(&tegra_wm8903_hp_jack, 183 snd_soc_jack_add_pins(&tegra_wm8903_hp_jack,
@@ -226,9 +215,6 @@ static int tegra_wm8903_remove(struct snd_soc_card *card)
226static struct snd_soc_dai_link tegra_wm8903_dai = { 215static struct snd_soc_dai_link tegra_wm8903_dai = {
227 .name = "WM8903", 216 .name = "WM8903",
228 .stream_name = "WM8903 PCM", 217 .stream_name = "WM8903 PCM",
229 .codec_name = "wm8903.0-001a",
230 .platform_name = "tegra20-i2s.0",
231 .cpu_dai_name = "tegra20-i2s.0",
232 .codec_dai_name = "wm8903-hifi", 218 .codec_dai_name = "wm8903-hifi",
233 .init = tegra_wm8903_init, 219 .init = tegra_wm8903_init,
234 .ops = &tegra_wm8903_ops, 220 .ops = &tegra_wm8903_ops,
@@ -257,96 +243,25 @@ static int tegra_wm8903_driver_probe(struct platform_device *pdev)
257 struct device_node *np = pdev->dev.of_node; 243 struct device_node *np = pdev->dev.of_node;
258 struct snd_soc_card *card = &snd_soc_tegra_wm8903; 244 struct snd_soc_card *card = &snd_soc_tegra_wm8903;
259 struct tegra_wm8903 *machine; 245 struct tegra_wm8903 *machine;
260 struct tegra_wm8903_platform_data *pdata;
261 int ret; 246 int ret;
262 247
263 if (!pdev->dev.platform_data && !pdev->dev.of_node) {
264 dev_err(&pdev->dev, "No platform data supplied\n");
265 return -EINVAL;
266 }
267
268 machine = devm_kzalloc(&pdev->dev, sizeof(struct tegra_wm8903), 248 machine = devm_kzalloc(&pdev->dev, sizeof(struct tegra_wm8903),
269 GFP_KERNEL); 249 GFP_KERNEL);
270 if (!machine) { 250 if (!machine) {
271 dev_err(&pdev->dev, "Can't allocate tegra_wm8903 struct\n"); 251 dev_err(&pdev->dev, "Can't allocate tegra_wm8903 struct\n");
272 ret = -ENOMEM; 252 return -ENOMEM;
273 goto err;
274 } 253 }
275 pdata = &machine->pdata;
276 254
277 card->dev = &pdev->dev; 255 card->dev = &pdev->dev;
278 platform_set_drvdata(pdev, card); 256 platform_set_drvdata(pdev, card);
279 snd_soc_card_set_drvdata(card, machine); 257 snd_soc_card_set_drvdata(card, machine);
280 258
281 if (pdev->dev.platform_data) { 259 machine->gpio_spkr_en = of_get_named_gpio(np, "nvidia,spkr-en-gpios",
282 memcpy(pdata, card->dev->platform_data, sizeof(*pdata)); 260 0);
283 } else if (np) { 261 if (machine->gpio_spkr_en == -EPROBE_DEFER)
284 pdata->gpio_spkr_en = of_get_named_gpio(np, 262 return -EPROBE_DEFER;
285 "nvidia,spkr-en-gpios", 0); 263 if (gpio_is_valid(machine->gpio_spkr_en)) {
286 if (pdata->gpio_spkr_en == -EPROBE_DEFER) 264 ret = devm_gpio_request_one(&pdev->dev, machine->gpio_spkr_en,
287 return -EPROBE_DEFER;
288
289 pdata->gpio_hp_mute = of_get_named_gpio(np,
290 "nvidia,hp-mute-gpios", 0);
291 if (pdata->gpio_hp_mute == -EPROBE_DEFER)
292 return -EPROBE_DEFER;
293
294 pdata->gpio_hp_det = of_get_named_gpio(np,
295 "nvidia,hp-det-gpios", 0);
296 if (pdata->gpio_hp_det == -EPROBE_DEFER)
297 return -EPROBE_DEFER;
298
299 pdata->gpio_int_mic_en = of_get_named_gpio(np,
300 "nvidia,int-mic-en-gpios", 0);
301 if (pdata->gpio_int_mic_en == -EPROBE_DEFER)
302 return -EPROBE_DEFER;
303
304 pdata->gpio_ext_mic_en = of_get_named_gpio(np,
305 "nvidia,ext-mic-en-gpios", 0);
306 if (pdata->gpio_ext_mic_en == -EPROBE_DEFER)
307 return -EPROBE_DEFER;
308 }
309
310 if (np) {
311 ret = snd_soc_of_parse_card_name(card, "nvidia,model");
312 if (ret)
313 goto err;
314
315 ret = snd_soc_of_parse_audio_routing(card,
316 "nvidia,audio-routing");
317 if (ret)
318 goto err;
319
320 tegra_wm8903_dai.codec_name = NULL;
321 tegra_wm8903_dai.codec_of_node = of_parse_phandle(np,
322 "nvidia,audio-codec", 0);
323 if (!tegra_wm8903_dai.codec_of_node) {
324 dev_err(&pdev->dev,
325 "Property 'nvidia,audio-codec' missing or invalid\n");
326 ret = -EINVAL;
327 goto err;
328 }
329
330 tegra_wm8903_dai.cpu_dai_name = NULL;
331 tegra_wm8903_dai.cpu_of_node = of_parse_phandle(np,
332 "nvidia,i2s-controller", 0);
333 if (!tegra_wm8903_dai.cpu_of_node) {
334 dev_err(&pdev->dev,
335 "Property 'nvidia,i2s-controller' missing or invalid\n");
336 ret = -EINVAL;
337 goto err;
338 }
339
340 tegra_wm8903_dai.platform_name = NULL;
341 tegra_wm8903_dai.platform_of_node =
342 tegra_wm8903_dai.cpu_of_node;
343 } else {
344 card->dapm_routes = harmony_audio_map;
345 card->num_dapm_routes = ARRAY_SIZE(harmony_audio_map);
346 }
347
348 if (gpio_is_valid(pdata->gpio_spkr_en)) {
349 ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_spkr_en,
350 GPIOF_OUT_INIT_LOW, "spkr_en"); 265 GPIOF_OUT_INIT_LOW, "spkr_en");
351 if (ret) { 266 if (ret) {
352 dev_err(card->dev, "cannot get spkr_en gpio\n"); 267 dev_err(card->dev, "cannot get spkr_en gpio\n");
@@ -354,8 +269,12 @@ static int tegra_wm8903_driver_probe(struct platform_device *pdev)
354 } 269 }
355 } 270 }
356 271
357 if (gpio_is_valid(pdata->gpio_hp_mute)) { 272 machine->gpio_hp_mute = of_get_named_gpio(np, "nvidia,hp-mute-gpios",
358 ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_hp_mute, 273 0);
274 if (machine->gpio_hp_mute == -EPROBE_DEFER)
275 return -EPROBE_DEFER;
276 if (gpio_is_valid(machine->gpio_hp_mute)) {
277 ret = devm_gpio_request_one(&pdev->dev, machine->gpio_hp_mute,
359 GPIOF_OUT_INIT_HIGH, "hp_mute"); 278 GPIOF_OUT_INIT_HIGH, "hp_mute");
360 if (ret) { 279 if (ret) {
361 dev_err(card->dev, "cannot get hp_mute gpio\n"); 280 dev_err(card->dev, "cannot get hp_mute gpio\n");
@@ -363,9 +282,18 @@ static int tegra_wm8903_driver_probe(struct platform_device *pdev)
363 } 282 }
364 } 283 }
365 284
366 if (gpio_is_valid(pdata->gpio_int_mic_en)) { 285 machine->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0);
286 if (machine->gpio_hp_det == -EPROBE_DEFER)
287 return -EPROBE_DEFER;
288
289 machine->gpio_int_mic_en = of_get_named_gpio(np,
290 "nvidia,int-mic-en-gpios", 0);
291 if (machine->gpio_int_mic_en == -EPROBE_DEFER)
292 return -EPROBE_DEFER;
293 if (gpio_is_valid(machine->gpio_int_mic_en)) {
367 /* Disable int mic; enable signal is active-high */ 294 /* Disable int mic; enable signal is active-high */
368 ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_int_mic_en, 295 ret = devm_gpio_request_one(&pdev->dev,
296 machine->gpio_int_mic_en,
369 GPIOF_OUT_INIT_LOW, "int_mic_en"); 297 GPIOF_OUT_INIT_LOW, "int_mic_en");
370 if (ret) { 298 if (ret) {
371 dev_err(card->dev, "cannot get int_mic_en gpio\n"); 299 dev_err(card->dev, "cannot get int_mic_en gpio\n");
@@ -373,9 +301,14 @@ static int tegra_wm8903_driver_probe(struct platform_device *pdev)
373 } 301 }
374 } 302 }
375 303
376 if (gpio_is_valid(pdata->gpio_ext_mic_en)) { 304 machine->gpio_ext_mic_en = of_get_named_gpio(np,
305 "nvidia,ext-mic-en-gpios", 0);
306 if (machine->gpio_ext_mic_en == -EPROBE_DEFER)
307 return -EPROBE_DEFER;
308 if (gpio_is_valid(machine->gpio_ext_mic_en)) {
377 /* Enable ext mic; enable signal is active-low */ 309 /* Enable ext mic; enable signal is active-low */
378 ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_ext_mic_en, 310 ret = devm_gpio_request_one(&pdev->dev,
311 machine->gpio_ext_mic_en,
379 GPIOF_OUT_INIT_LOW, "ext_mic_en"); 312 GPIOF_OUT_INIT_LOW, "ext_mic_en");
380 if (ret) { 313 if (ret) {
381 dev_err(card->dev, "cannot get ext_mic_en gpio\n"); 314 dev_err(card->dev, "cannot get ext_mic_en gpio\n");
@@ -383,6 +316,34 @@ static int tegra_wm8903_driver_probe(struct platform_device *pdev)
383 } 316 }
384 } 317 }
385 318
319 ret = snd_soc_of_parse_card_name(card, "nvidia,model");
320 if (ret)
321 goto err;
322
323 ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing");
324 if (ret)
325 goto err;
326
327 tegra_wm8903_dai.codec_of_node = of_parse_phandle(np,
328 "nvidia,audio-codec", 0);
329 if (!tegra_wm8903_dai.codec_of_node) {
330 dev_err(&pdev->dev,
331 "Property 'nvidia,audio-codec' missing or invalid\n");
332 ret = -EINVAL;
333 goto err;
334 }
335
336 tegra_wm8903_dai.cpu_of_node = of_parse_phandle(np,
337 "nvidia,i2s-controller", 0);
338 if (!tegra_wm8903_dai.cpu_of_node) {
339 dev_err(&pdev->dev,
340 "Property 'nvidia,i2s-controller' missing or invalid\n");
341 ret = -EINVAL;
342 goto err;
343 }
344
345 tegra_wm8903_dai.platform_of_node = tegra_wm8903_dai.cpu_of_node;
346
386 ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); 347 ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
387 if (ret) 348 if (ret)
388 goto err; 349 goto err;
diff --git a/sound/soc/tegra/tegra_wm9712.c b/sound/soc/tegra/tegra_wm9712.c
index 68d42403d9b5..5e119630b0e0 100644
--- a/sound/soc/tegra/tegra_wm9712.c
+++ b/sound/soc/tegra/tegra_wm9712.c
@@ -55,7 +55,7 @@ static int tegra_wm9712_init(struct snd_soc_pcm_runtime *rtd)
55static struct snd_soc_dai_link tegra_wm9712_dai = { 55static struct snd_soc_dai_link tegra_wm9712_dai = {
56 .name = "AC97 HiFi", 56 .name = "AC97 HiFi",
57 .stream_name = "AC97 HiFi", 57 .stream_name = "AC97 HiFi",
58 .cpu_dai_name = "tegra-ac97-pcm", 58 .cpu_dai_name = "tegra20-ac97",
59 .codec_dai_name = "wm9712-hifi", 59 .codec_dai_name = "wm9712-hifi",
60 .codec_name = "wm9712-codec", 60 .codec_name = "wm9712-codec",
61 .init = tegra_wm9712_init, 61 .init = tegra_wm9712_init,
@@ -79,11 +79,6 @@ static int tegra_wm9712_driver_probe(struct platform_device *pdev)
79 struct tegra_wm9712 *machine; 79 struct tegra_wm9712 *machine;
80 int ret; 80 int ret;
81 81
82 if (!pdev->dev.of_node) {
83 dev_err(&pdev->dev, "No platform data supplied\n");
84 return -EINVAL;
85 }
86
87 machine = devm_kzalloc(&pdev->dev, sizeof(struct tegra_wm9712), 82 machine = devm_kzalloc(&pdev->dev, sizeof(struct tegra_wm9712),
88 GFP_KERNEL); 83 GFP_KERNEL);
89 if (!machine) { 84 if (!machine) {
diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c
index 7fcf6c2297db..05c68aab5cf0 100644
--- a/sound/soc/tegra/trimslice.c
+++ b/sound/soc/tegra/trimslice.c
@@ -97,9 +97,6 @@ static const struct snd_soc_dapm_route trimslice_audio_map[] = {
97static struct snd_soc_dai_link trimslice_tlv320aic23_dai = { 97static struct snd_soc_dai_link trimslice_tlv320aic23_dai = {
98 .name = "TLV320AIC23", 98 .name = "TLV320AIC23",
99 .stream_name = "AIC23", 99 .stream_name = "AIC23",
100 .codec_name = "tlv320aic23-codec.2-001a",
101 .platform_name = "tegra20-i2s.0",
102 .cpu_dai_name = "tegra20-i2s.0",
103 .codec_dai_name = "tlv320aic23-hifi", 100 .codec_dai_name = "tlv320aic23-hifi",
104 .ops = &trimslice_asoc_ops, 101 .ops = &trimslice_asoc_ops,
105 .dai_fmt = SND_SOC_DAIFMT_I2S | 102 .dai_fmt = SND_SOC_DAIFMT_I2S |
@@ -122,6 +119,7 @@ static struct snd_soc_card snd_soc_trimslice = {
122 119
123static int tegra_snd_trimslice_probe(struct platform_device *pdev) 120static int tegra_snd_trimslice_probe(struct platform_device *pdev)
124{ 121{
122 struct device_node *np = pdev->dev.of_node;
125 struct snd_soc_card *card = &snd_soc_trimslice; 123 struct snd_soc_card *card = &snd_soc_trimslice;
126 struct tegra_trimslice *trimslice; 124 struct tegra_trimslice *trimslice;
127 int ret; 125 int ret;
@@ -130,44 +128,38 @@ static int tegra_snd_trimslice_probe(struct platform_device *pdev)
130 GFP_KERNEL); 128 GFP_KERNEL);
131 if (!trimslice) { 129 if (!trimslice) {
132 dev_err(&pdev->dev, "Can't allocate tegra_trimslice\n"); 130 dev_err(&pdev->dev, "Can't allocate tegra_trimslice\n");
133 ret = -ENOMEM; 131 return -ENOMEM;
132 }
133
134 card->dev = &pdev->dev;
135 platform_set_drvdata(pdev, card);
136 snd_soc_card_set_drvdata(card, trimslice);
137
138 trimslice_tlv320aic23_dai.codec_of_node = of_parse_phandle(np,
139 "nvidia,audio-codec", 0);
140 if (!trimslice_tlv320aic23_dai.codec_of_node) {
141 dev_err(&pdev->dev,
142 "Property 'nvidia,audio-codec' missing or invalid\n");
143 ret = -EINVAL;
134 goto err; 144 goto err;
135 } 145 }
136 146
137 if (pdev->dev.of_node) { 147 trimslice_tlv320aic23_dai.cpu_of_node = of_parse_phandle(np,
138 trimslice_tlv320aic23_dai.codec_name = NULL; 148 "nvidia,i2s-controller", 0);
139 trimslice_tlv320aic23_dai.codec_of_node = of_parse_phandle( 149 if (!trimslice_tlv320aic23_dai.cpu_of_node) {
140 pdev->dev.of_node, "nvidia,audio-codec", 0); 150 dev_err(&pdev->dev,
141 if (!trimslice_tlv320aic23_dai.codec_of_node) { 151 "Property 'nvidia,i2s-controller' missing or invalid\n");
142 dev_err(&pdev->dev, 152 ret = -EINVAL;
143 "Property 'nvidia,audio-codec' missing or invalid\n"); 153 goto err;
144 ret = -EINVAL;
145 goto err;
146 }
147
148 trimslice_tlv320aic23_dai.cpu_dai_name = NULL;
149 trimslice_tlv320aic23_dai.cpu_of_node = of_parse_phandle(
150 pdev->dev.of_node, "nvidia,i2s-controller", 0);
151 if (!trimslice_tlv320aic23_dai.cpu_of_node) {
152 dev_err(&pdev->dev,
153 "Property 'nvidia,i2s-controller' missing or invalid\n");
154 ret = -EINVAL;
155 goto err;
156 }
157
158 trimslice_tlv320aic23_dai.platform_name = NULL;
159 trimslice_tlv320aic23_dai.platform_of_node =
160 trimslice_tlv320aic23_dai.cpu_of_node;
161 } 154 }
162 155
156 trimslice_tlv320aic23_dai.platform_of_node =
157 trimslice_tlv320aic23_dai.cpu_of_node;
158
163 ret = tegra_asoc_utils_init(&trimslice->util_data, &pdev->dev); 159 ret = tegra_asoc_utils_init(&trimslice->util_data, &pdev->dev);
164 if (ret) 160 if (ret)
165 goto err; 161 goto err;
166 162
167 card->dev = &pdev->dev;
168 platform_set_drvdata(pdev, card);
169 snd_soc_card_set_drvdata(card, trimslice);
170
171 ret = snd_soc_register_card(card); 163 ret = snd_soc_register_card(card);
172 if (ret) { 164 if (ret) {
173 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", 165 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c
index 16ab69635e2e..8a2840304d28 100644
--- a/sound/soc/txx9/txx9aclc-ac97.c
+++ b/sound/soc/txx9/txx9aclc-ac97.c
@@ -170,6 +170,10 @@ static struct snd_soc_dai_driver txx9aclc_ac97_dai = {
170 }, 170 },
171}; 171};
172 172
173static const struct snd_soc_component_driver txx9aclc_ac97_component = {
174 .name = "txx9aclc-ac97",
175};
176
173static int txx9aclc_ac97_dev_probe(struct platform_device *pdev) 177static int txx9aclc_ac97_dev_probe(struct platform_device *pdev)
174{ 178{
175 struct txx9aclc_plat_drvdata *drvdata; 179 struct txx9aclc_plat_drvdata *drvdata;
@@ -205,12 +209,13 @@ static int txx9aclc_ac97_dev_probe(struct platform_device *pdev)
205 if (err < 0) 209 if (err < 0)
206 return err; 210 return err;
207 211
208 return snd_soc_register_dai(&pdev->dev, &txx9aclc_ac97_dai); 212 return snd_soc_register_component(&pdev->dev, &txx9aclc_ac97_component,
213 &txx9aclc_ac97_dai, 1);
209} 214}
210 215
211static int txx9aclc_ac97_dev_remove(struct platform_device *pdev) 216static int txx9aclc_ac97_dev_remove(struct platform_device *pdev)
212{ 217{
213 snd_soc_unregister_dai(&pdev->dev); 218 snd_soc_unregister_component(&pdev->dev);
214 return 0; 219 return 0;
215} 220}
216 221
diff --git a/sound/soc/ux500/Kconfig b/sound/soc/ux500/Kconfig
index 6b799c0e88df..aa5011894c74 100644
--- a/sound/soc/ux500/Kconfig
+++ b/sound/soc/ux500/Kconfig
@@ -16,7 +16,7 @@ config SND_SOC_UX500_PLAT_MSP_I2S
16config SND_SOC_UX500_PLAT_DMA 16config SND_SOC_UX500_PLAT_DMA
17 tristate "Platform - DB8500 (DMA)" 17 tristate "Platform - DB8500 (DMA)"
18 depends on SND_SOC_UX500 18 depends on SND_SOC_UX500
19 select SND_SOC_DMAENGINE_PCM 19 select SND_SOC_GENERIC_DMAENGINE_PCM
20 help 20 help
21 Say Y if you want to enable the Ux500 platform-driver. 21 Say Y if you want to enable the Ux500 platform-driver.
22 22
diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c
index 54028cf76511..7d5fc1328523 100644
--- a/sound/soc/ux500/ux500_msp_dai.c
+++ b/sound/soc/ux500/ux500_msp_dai.c
@@ -766,6 +766,11 @@ static struct snd_soc_dai_driver ux500_msp_dai_drv[UX500_NBR_OF_DAI] = {
766 }, 766 },
767}; 767};
768 768
769static const struct snd_soc_component_driver ux500_msp_component = {
770 .name = "ux500-msp",
771};
772
773
769static int ux500_msp_drv_probe(struct platform_device *pdev) 774static int ux500_msp_drv_probe(struct platform_device *pdev)
770{ 775{
771 struct ux500_msp_i2s_drvdata *drvdata; 776 struct ux500_msp_i2s_drvdata *drvdata;
@@ -823,8 +828,8 @@ static int ux500_msp_drv_probe(struct platform_device *pdev)
823 } 828 }
824 dev_set_drvdata(&pdev->dev, drvdata); 829 dev_set_drvdata(&pdev->dev, drvdata);
825 830
826 ret = snd_soc_register_dai(&pdev->dev, 831 ret = snd_soc_register_component(&pdev->dev, &ux500_msp_component,
827 &ux500_msp_dai_drv[drvdata->msp->id]); 832 &ux500_msp_dai_drv[drvdata->msp->id], 1);
828 if (ret < 0) { 833 if (ret < 0) {
829 dev_err(&pdev->dev, "Error: %s: Failed to register MSP%d!\n", 834 dev_err(&pdev->dev, "Error: %s: Failed to register MSP%d!\n",
830 __func__, drvdata->msp->id); 835 __func__, drvdata->msp->id);
@@ -842,7 +847,7 @@ static int ux500_msp_drv_probe(struct platform_device *pdev)
842 return 0; 847 return 0;
843 848
844err_reg_plat: 849err_reg_plat:
845 snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(ux500_msp_dai_drv)); 850 snd_soc_unregister_component(&pdev->dev);
846err_init_msp: 851err_init_msp:
847 clk_put(drvdata->clk); 852 clk_put(drvdata->clk);
848err_clk: 853err_clk:
@@ -859,7 +864,7 @@ static int ux500_msp_drv_remove(struct platform_device *pdev)
859 864
860 ux500_pcm_unregister_platform(pdev); 865 ux500_pcm_unregister_platform(pdev);
861 866
862 snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(ux500_msp_dai_drv)); 867 snd_soc_unregister_component(&pdev->dev);
863 868
864 devm_regulator_put(drvdata->reg_vape); 869 devm_regulator_put(drvdata->reg_vape);
865 prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, "ux500_msp_i2s"); 870 prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, "ux500_msp_i2s");
diff --git a/sound/soc/ux500/ux500_msp_dai.h b/sound/soc/ux500/ux500_msp_dai.h
index 9c778d9c3838..f53104359f15 100644
--- a/sound/soc/ux500/ux500_msp_dai.h
+++ b/sound/soc/ux500/ux500_msp_dai.h
@@ -35,13 +35,8 @@
35#define FRAME_PER_8_SLOTS 138 35#define FRAME_PER_8_SLOTS 138
36#define FRAME_PER_16_SLOTS 277 36#define FRAME_PER_16_SLOTS 277
37 37
38#ifndef CONFIG_SND_SOC_UX500_AB5500
39#define UX500_MSP_INTERNAL_CLOCK_FREQ 40000000 38#define UX500_MSP_INTERNAL_CLOCK_FREQ 40000000
40#define UX500_MSP1_INTERNAL_CLOCK_FREQ UX500_MSP_INTERNAL_CLOCK_FREQ 39#define UX500_MSP1_INTERNAL_CLOCK_FREQ UX500_MSP_INTERNAL_CLOCK_FREQ
41#else
42#define UX500_MSP_INTERNAL_CLOCK_FREQ 13000000
43#define UX500_MSP1_INTERNAL_CLOCK_FREQ (UX500_MSP_INTERNAL_CLOCK_FREQ * 2)
44#endif
45 40
46#define UX500_MSP_MIN_CHANNELS 1 41#define UX500_MSP_MIN_CHANNELS 1
47#define UX500_MSP_MAX_CHANNELS 8 42#define UX500_MSP_MAX_CHANNELS 8
diff --git a/sound/soc/ux500/ux500_msp_i2s.h b/sound/soc/ux500/ux500_msp_i2s.h
index 437f0c032c58..e5cd105c90f9 100644
--- a/sound/soc/ux500/ux500_msp_i2s.h
+++ b/sound/soc/ux500/ux500_msp_i2s.h
@@ -541,6 +541,7 @@ struct ux500_msp_dma_params {
541 struct stedma40_chan_cfg *dma_cfg; 541 struct stedma40_chan_cfg *dma_cfg;
542}; 542};
543 543
544struct msp_i2s_platform_data;
544int ux500_msp_i2s_init_msp(struct platform_device *pdev, 545int ux500_msp_i2s_init_msp(struct platform_device *pdev,
545 struct ux500_msp **msp_p, 546 struct ux500_msp **msp_p,
546 struct msp_i2s_platform_data *platform_data); 547 struct msp_i2s_platform_data *platform_data);
diff --git a/sound/soc/ux500/ux500_pcm.c b/sound/soc/ux500/ux500_pcm.c
index 846fa82a58d0..b6e5ae277299 100644
--- a/sound/soc/ux500/ux500_pcm.c
+++ b/sound/soc/ux500/ux500_pcm.c
@@ -28,28 +28,19 @@
28#include "ux500_msp_i2s.h" 28#include "ux500_msp_i2s.h"
29#include "ux500_pcm.h" 29#include "ux500_pcm.h"
30 30
31static struct snd_pcm_hardware ux500_pcm_hw_playback = { 31#define UX500_PLATFORM_MIN_RATE 8000
32 .info = SNDRV_PCM_INFO_INTERLEAVED | 32#define UX500_PLATFORM_MAX_RATE 48000
33 SNDRV_PCM_INFO_MMAP | 33
34 SNDRV_PCM_INFO_RESUME | 34#define UX500_PLATFORM_MIN_CHANNELS 1
35 SNDRV_PCM_INFO_PAUSE, 35#define UX500_PLATFORM_MAX_CHANNELS 8
36 .formats = SNDRV_PCM_FMTBIT_S16_LE |
37 SNDRV_PCM_FMTBIT_U16_LE |
38 SNDRV_PCM_FMTBIT_S16_BE |
39 SNDRV_PCM_FMTBIT_U16_BE,
40 .rates = SNDRV_PCM_RATE_KNOT,
41 .rate_min = UX500_PLATFORM_MIN_RATE_PLAYBACK,
42 .rate_max = UX500_PLATFORM_MAX_RATE_PLAYBACK,
43 .channels_min = UX500_PLATFORM_MIN_CHANNELS,
44 .channels_max = UX500_PLATFORM_MAX_CHANNELS,
45 .buffer_bytes_max = UX500_PLATFORM_BUFFER_BYTES_MAX,
46 .period_bytes_min = UX500_PLATFORM_PERIODS_BYTES_MIN,
47 .period_bytes_max = UX500_PLATFORM_PERIODS_BYTES_MAX,
48 .periods_min = UX500_PLATFORM_PERIODS_MIN,
49 .periods_max = UX500_PLATFORM_PERIODS_MAX,
50};
51 36
52static struct snd_pcm_hardware ux500_pcm_hw_capture = { 37#define UX500_PLATFORM_PERIODS_BYTES_MIN 128
38#define UX500_PLATFORM_PERIODS_BYTES_MAX (64 * PAGE_SIZE)
39#define UX500_PLATFORM_PERIODS_MIN 2
40#define UX500_PLATFORM_PERIODS_MAX 48
41#define UX500_PLATFORM_BUFFER_BYTES_MAX (2048 * PAGE_SIZE)
42
43static const struct snd_pcm_hardware ux500_pcm_hw = {
53 .info = SNDRV_PCM_INFO_INTERLEAVED | 44 .info = SNDRV_PCM_INFO_INTERLEAVED |
54 SNDRV_PCM_INFO_MMAP | 45 SNDRV_PCM_INFO_MMAP |
55 SNDRV_PCM_INFO_RESUME | 46 SNDRV_PCM_INFO_RESUME |
@@ -59,8 +50,8 @@ static struct snd_pcm_hardware ux500_pcm_hw_capture = {
59 SNDRV_PCM_FMTBIT_S16_BE | 50 SNDRV_PCM_FMTBIT_S16_BE |
60 SNDRV_PCM_FMTBIT_U16_BE, 51 SNDRV_PCM_FMTBIT_U16_BE,
61 .rates = SNDRV_PCM_RATE_KNOT, 52 .rates = SNDRV_PCM_RATE_KNOT,
62 .rate_min = UX500_PLATFORM_MIN_RATE_CAPTURE, 53 .rate_min = UX500_PLATFORM_MIN_RATE,
63 .rate_max = UX500_PLATFORM_MAX_RATE_CAPTURE, 54 .rate_max = UX500_PLATFORM_MAX_RATE,
64 .channels_min = UX500_PLATFORM_MIN_CHANNELS, 55 .channels_min = UX500_PLATFORM_MIN_CHANNELS,
65 .channels_max = UX500_PLATFORM_MAX_CHANNELS, 56 .channels_max = UX500_PLATFORM_MAX_CHANNELS,
66 .buffer_bytes_max = UX500_PLATFORM_BUFFER_BYTES_MAX, 57 .buffer_bytes_max = UX500_PLATFORM_BUFFER_BYTES_MAX,
@@ -70,64 +61,23 @@ static struct snd_pcm_hardware ux500_pcm_hw_capture = {
70 .periods_max = UX500_PLATFORM_PERIODS_MAX, 61 .periods_max = UX500_PLATFORM_PERIODS_MAX,
71}; 62};
72 63
73static void ux500_pcm_dma_hw_free(struct device *dev, 64static struct dma_chan *ux500_pcm_request_chan(struct snd_soc_pcm_runtime *rtd,
74 struct snd_pcm_substream *substream) 65 struct snd_pcm_substream *substream)
75{ 66{
76 struct snd_pcm_runtime *runtime = substream->runtime;
77 struct snd_dma_buffer *buf = runtime->dma_buffer_p;
78
79 if (runtime->dma_area == NULL)
80 return;
81
82 if (buf != &substream->dma_buffer) {
83 dma_free_coherent(buf->dev.dev, buf->bytes, buf->area,
84 buf->addr);
85 kfree(runtime->dma_buffer_p);
86 }
87
88 snd_pcm_set_runtime_buffer(substream, NULL);
89}
90
91static int ux500_pcm_open(struct snd_pcm_substream *substream)
92{
93 int stream_id = substream->pstr->stream;
94 struct snd_pcm_runtime *runtime = substream->runtime;
95 struct snd_soc_pcm_runtime *rtd = substream->private_data;
96 struct snd_soc_dai *dai = rtd->cpu_dai; 67 struct snd_soc_dai *dai = rtd->cpu_dai;
97 struct device *dev = dai->dev; 68 struct device *dev = dai->dev;
98 int ret;
99 struct ux500_msp_dma_params *dma_params;
100 u16 per_data_width, mem_data_width; 69 u16 per_data_width, mem_data_width;
101 struct stedma40_chan_cfg *dma_cfg; 70 struct stedma40_chan_cfg *dma_cfg;
71 struct ux500_msp_dma_params *dma_params;
102 72
103 dev_dbg(dev, "%s: MSP %d (%s): Enter.\n", __func__, dai->id, 73 dev_dbg(dev, "%s: MSP %d (%s): Enter.\n", __func__, dai->id,
104 snd_pcm_stream_str(substream)); 74 snd_pcm_stream_str(substream));
105 75
106 dev_dbg(dev, "%s: Set runtime hwparams.\n", __func__); 76 dma_params = snd_soc_dai_get_dma_data(dai, substream);
107 if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) 77 dma_cfg = dma_params->dma_cfg;
108 snd_soc_set_runtime_hwparams(substream,
109 &ux500_pcm_hw_playback);
110 else
111 snd_soc_set_runtime_hwparams(substream,
112 &ux500_pcm_hw_capture);
113
114 /* ensure that buffer size is a multiple of period size */
115 ret = snd_pcm_hw_constraint_integer(runtime,
116 SNDRV_PCM_HW_PARAM_PERIODS);
117 if (ret < 0) {
118 dev_err(dev, "%s: Error: snd_pcm_hw_constraints failed (%d)\n",
119 __func__, ret);
120 return ret;
121 }
122
123 dev_dbg(dev, "%s: Set hw-struct for %s.\n", __func__,
124 snd_pcm_stream_str(substream));
125 runtime->hw = (stream_id == SNDRV_PCM_STREAM_PLAYBACK) ?
126 ux500_pcm_hw_playback : ux500_pcm_hw_capture;
127 78
128 mem_data_width = STEDMA40_HALFWORD_WIDTH; 79 mem_data_width = STEDMA40_HALFWORD_WIDTH;
129 80
130 dma_params = snd_soc_dai_get_dma_data(dai, substream);
131 switch (dma_params->data_size) { 81 switch (dma_params->data_size) {
132 case 32: 82 case 32:
133 per_data_width = STEDMA40_WORD_WIDTH; 83 per_data_width = STEDMA40_WORD_WIDTH;
@@ -140,13 +90,8 @@ static int ux500_pcm_open(struct snd_pcm_substream *substream)
140 break; 90 break;
141 default: 91 default:
142 per_data_width = STEDMA40_WORD_WIDTH; 92 per_data_width = STEDMA40_WORD_WIDTH;
143 dev_warn(rtd->platform->dev,
144 "%s: Unknown data-size (%d)! Assuming 32 bits.\n",
145 __func__, dma_params->data_size);
146 } 93 }
147 94
148 dma_cfg = dma_params->dma_cfg;
149
150 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 95 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
151 dma_cfg->src_info.data_width = mem_data_width; 96 dma_cfg->src_info.data_width = mem_data_width;
152 dma_cfg->dst_info.data_width = per_data_width; 97 dma_cfg->dst_info.data_width = per_data_width;
@@ -155,137 +100,24 @@ static int ux500_pcm_open(struct snd_pcm_substream *substream)
155 dma_cfg->dst_info.data_width = mem_data_width; 100 dma_cfg->dst_info.data_width = mem_data_width;
156 } 101 }
157 102
158 103 return snd_dmaengine_pcm_request_channel(stedma40_filter, dma_cfg);
159 ret = snd_dmaengine_pcm_open(substream, stedma40_filter, dma_cfg);
160 if (ret) {
161 dev_dbg(dai->dev,
162 "%s: ERROR: snd_dmaengine_pcm_open failed (%d)!\n",
163 __func__, ret);
164 return ret;
165 }
166
167 snd_dmaengine_pcm_set_data(substream, dma_cfg);
168
169 return 0;
170}
171
172static int ux500_pcm_close(struct snd_pcm_substream *substream)
173{
174 struct snd_soc_pcm_runtime *rtd = substream->private_data;
175 struct snd_soc_dai *dai = rtd->cpu_dai;
176
177 dev_dbg(dai->dev, "%s: Enter\n", __func__);
178
179 snd_dmaengine_pcm_close(substream);
180
181 return 0;
182}
183
184static int ux500_pcm_hw_params(struct snd_pcm_substream *substream,
185 struct snd_pcm_hw_params *hw_params)
186{
187 struct snd_pcm_runtime *runtime = substream->runtime;
188 struct snd_dma_buffer *buf = runtime->dma_buffer_p;
189 struct snd_soc_pcm_runtime *rtd = substream->private_data;
190 int ret = 0;
191 int size;
192
193 dev_dbg(rtd->platform->dev, "%s: Enter\n", __func__);
194
195 size = params_buffer_bytes(hw_params);
196
197 if (buf) {
198 if (buf->bytes >= size)
199 goto out;
200 ux500_pcm_dma_hw_free(NULL, substream);
201 }
202
203 if (substream->dma_buffer.area != NULL &&
204 substream->dma_buffer.bytes >= size) {
205 buf = &substream->dma_buffer;
206 } else {
207 buf = kmalloc(sizeof(struct snd_dma_buffer), GFP_KERNEL);
208 if (!buf)
209 goto nomem;
210
211 buf->dev.type = SNDRV_DMA_TYPE_DEV;
212 buf->dev.dev = NULL;
213 buf->area = dma_alloc_coherent(NULL, size, &buf->addr,
214 GFP_KERNEL);
215 buf->bytes = size;
216 buf->private_data = NULL;
217
218 if (!buf->area)
219 goto free;
220 }
221 snd_pcm_set_runtime_buffer(substream, buf);
222 ret = 1;
223 out:
224 runtime->dma_bytes = size;
225 return ret;
226
227 free:
228 kfree(buf);
229 nomem:
230 return -ENOMEM;
231} 104}
232 105
233static int ux500_pcm_hw_free(struct snd_pcm_substream *substream) 106static const struct snd_dmaengine_pcm_config ux500_dmaengine_pcm_config = {
234{ 107 .pcm_hardware = &ux500_pcm_hw,
235 struct snd_soc_pcm_runtime *rtd = substream->private_data; 108 .compat_request_channel = ux500_pcm_request_chan,
236 109 .prealloc_buffer_size = 128 * 1024,
237 dev_dbg(rtd->platform->dev, "%s: Enter\n", __func__);
238
239 ux500_pcm_dma_hw_free(NULL, substream);
240
241 return 0;
242}
243
244static int ux500_pcm_mmap(struct snd_pcm_substream *substream,
245 struct vm_area_struct *vma)
246{
247 struct snd_pcm_runtime *runtime = substream->runtime;
248 struct snd_soc_pcm_runtime *rtd = substream->private_data;
249
250 dev_dbg(rtd->platform->dev, "%s: Enter.\n", __func__);
251
252 return dma_mmap_coherent(NULL, vma, runtime->dma_area,
253 runtime->dma_addr, runtime->dma_bytes);
254}
255
256static struct snd_pcm_ops ux500_pcm_ops = {
257 .open = ux500_pcm_open,
258 .close = ux500_pcm_close,
259 .ioctl = snd_pcm_lib_ioctl,
260 .hw_params = ux500_pcm_hw_params,
261 .hw_free = ux500_pcm_hw_free,
262 .trigger = snd_dmaengine_pcm_trigger,
263 .pointer = snd_dmaengine_pcm_pointer_no_residue,
264 .mmap = ux500_pcm_mmap
265};
266
267int ux500_pcm_new(struct snd_soc_pcm_runtime *rtd)
268{
269 struct snd_pcm *pcm = rtd->pcm;
270
271 dev_dbg(rtd->platform->dev, "%s: Enter (id = '%s').\n", __func__,
272 pcm->id);
273
274 pcm->info_flags = 0;
275
276 return 0;
277}
278
279static struct snd_soc_platform_driver ux500_pcm_soc_drv = {
280 .ops = &ux500_pcm_ops,
281 .pcm_new = ux500_pcm_new,
282}; 110};
283 111
284int ux500_pcm_register_platform(struct platform_device *pdev) 112int ux500_pcm_register_platform(struct platform_device *pdev)
285{ 113{
286 int ret; 114 int ret;
287 115
288 ret = snd_soc_register_platform(&pdev->dev, &ux500_pcm_soc_drv); 116 ret = snd_dmaengine_pcm_register(&pdev->dev,
117 &ux500_dmaengine_pcm_config,
118 SND_DMAENGINE_PCM_FLAG_NO_RESIDUE |
119 SND_DMAENGINE_PCM_FLAG_COMPAT |
120 SND_DMAENGINE_PCM_FLAG_NO_DT);
289 if (ret < 0) { 121 if (ret < 0) {
290 dev_err(&pdev->dev, 122 dev_err(&pdev->dev,
291 "%s: ERROR: Failed to register platform '%s' (%d)!\n", 123 "%s: ERROR: Failed to register platform '%s' (%d)!\n",
@@ -299,8 +131,7 @@ EXPORT_SYMBOL_GPL(ux500_pcm_register_platform);
299 131
300int ux500_pcm_unregister_platform(struct platform_device *pdev) 132int ux500_pcm_unregister_platform(struct platform_device *pdev)
301{ 133{
302 snd_soc_unregister_platform(&pdev->dev); 134 snd_dmaengine_pcm_unregister(&pdev->dev);
303
304 return 0; 135 return 0;
305} 136}
306EXPORT_SYMBOL_GPL(ux500_pcm_unregister_platform); 137EXPORT_SYMBOL_GPL(ux500_pcm_unregister_platform);
diff --git a/sound/soc/ux500/ux500_pcm.h b/sound/soc/ux500/ux500_pcm.h
index 76d344476afc..d76e1aff6458 100644
--- a/sound/soc/ux500/ux500_pcm.h
+++ b/sound/soc/ux500/ux500_pcm.h
@@ -18,20 +18,6 @@
18 18
19#include <linux/workqueue.h> 19#include <linux/workqueue.h>
20 20
21#define UX500_PLATFORM_MIN_RATE_PLAYBACK 8000
22#define UX500_PLATFORM_MAX_RATE_PLAYBACK 48000
23#define UX500_PLATFORM_MIN_RATE_CAPTURE 8000
24#define UX500_PLATFORM_MAX_RATE_CAPTURE 48000
25
26#define UX500_PLATFORM_MIN_CHANNELS 1
27#define UX500_PLATFORM_MAX_CHANNELS 8
28
29#define UX500_PLATFORM_PERIODS_BYTES_MIN 128
30#define UX500_PLATFORM_PERIODS_BYTES_MAX (64 * PAGE_SIZE)
31#define UX500_PLATFORM_PERIODS_MIN 2
32#define UX500_PLATFORM_PERIODS_MAX 48
33#define UX500_PLATFORM_BUFFER_BYTES_MAX (2048 * PAGE_SIZE)
34
35int ux500_pcm_register_platform(struct platform_device *pdev); 21int ux500_pcm_register_platform(struct platform_device *pdev);
36int ux500_pcm_unregister_platform(struct platform_device *pdev); 22int ux500_pcm_unregister_platform(struct platform_device *pdev);
37 23