aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/arm/pxa2xx-ac97.c4
-rw-r--r--sound/arm/pxa2xx-pcm-lib.c3
-rw-r--r--sound/soc/atmel/playpaq_wm8510.c2
-rw-r--r--sound/soc/au1x/psc-ac97.c129
-rw-r--r--sound/soc/au1x/psc.h1
-rw-r--r--sound/soc/blackfin/Kconfig8
-rw-r--r--sound/soc/blackfin/Makefile2
-rw-r--r--sound/soc/blackfin/bf5xx-ac97.c8
-rw-r--r--sound/soc/blackfin/bf5xx-ac97.h2
-rw-r--r--sound/soc/blackfin/bf5xx-ad1836.c135
-rw-r--r--sound/soc/blackfin/bf5xx-ad1938.c9
-rw-r--r--sound/soc/blackfin/bf5xx-i2s.c22
-rw-r--r--sound/soc/blackfin/bf5xx-i2s.h2
-rw-r--r--sound/soc/blackfin/bf5xx-sport.c2
-rw-r--r--sound/soc/blackfin/bf5xx-tdm-pcm.c9
-rw-r--r--sound/soc/blackfin/bf5xx-tdm.c45
-rw-r--r--sound/soc/blackfin/bf5xx-tdm.h11
-rw-r--r--sound/soc/codecs/Kconfig8
-rw-r--r--sound/soc/codecs/Makefile4
-rw-r--r--sound/soc/codecs/ad1836.c1
-rw-r--r--sound/soc/codecs/ad1938.c1
-rw-r--r--sound/soc/codecs/ak4642.c502
-rw-r--r--sound/soc/codecs/ak4642.h20
-rw-r--r--sound/soc/codecs/ak4671.c825
-rw-r--r--sound/soc/codecs/ak4671.h156
-rw-r--r--sound/soc/codecs/tlv320aic3x.c222
-rw-r--r--sound/soc/codecs/tlv320aic3x.h2
-rw-r--r--sound/soc/codecs/wm8350.c13
-rw-r--r--sound/soc/codecs/wm8400.c3
-rw-r--r--sound/soc/codecs/wm8510.c4
-rw-r--r--sound/soc/codecs/wm8580.c8
-rw-r--r--sound/soc/codecs/wm8753.c4
-rw-r--r--sound/soc/codecs/wm8900.c4
-rw-r--r--sound/soc/codecs/wm8940.c4
-rw-r--r--sound/soc/codecs/wm8960.c4
-rw-r--r--sound/soc/codecs/wm8974.c5
-rw-r--r--sound/soc/codecs/wm8990.c4
-rw-r--r--sound/soc/codecs/wm8993.c90
-rw-r--r--sound/soc/codecs/wm9705.c2
-rw-r--r--sound/soc/codecs/wm9713.c4
-rw-r--r--sound/soc/codecs/wm_hubs.c19
-rw-r--r--sound/soc/davinci/Kconfig4
-rw-r--r--sound/soc/davinci/davinci-evm.c33
-rw-r--r--sound/soc/davinci/davinci-mcasp.c24
-rw-r--r--sound/soc/fsl/mpc5200_dma.c33
-rw-r--r--sound/soc/imx/mx27vis_wm8974.c2
-rw-r--r--sound/soc/omap/n810.c12
-rw-r--r--sound/soc/omap/omap-mcbsp.c113
-rw-r--r--sound/soc/omap/omap-mcbsp.h4
-rw-r--r--sound/soc/omap/omap-pcm.c14
-rw-r--r--sound/soc/omap/omap-pcm.h2
-rw-r--r--sound/soc/omap/sdp3430.c15
-rw-r--r--sound/soc/pxa/magician.c2
-rw-r--r--sound/soc/pxa/pxa-ssp.c4
-rw-r--r--sound/soc/pxa/pxa2xx-ac97.c4
-rw-r--r--sound/soc/pxa/zylonite.c5
-rw-r--r--sound/soc/s3c24xx/Kconfig31
-rw-r--r--sound/soc/s3c24xx/Makefile9
-rw-r--r--sound/soc/s3c24xx/neo1973_gta02_wm8753.c2
-rw-r--r--sound/soc/s3c24xx/neo1973_wm8753.c2
-rw-r--r--sound/soc/s3c24xx/s3c-i2s-v2.c63
-rw-r--r--sound/soc/s3c24xx/s3c2443-ac97.c10
-rw-r--r--sound/soc/s3c24xx/s3c24xx-i2s.c5
-rw-r--r--sound/soc/s3c24xx/s3c24xx-pcm.c2
-rw-r--r--sound/soc/s3c24xx/s3c24xx_simtec.c394
-rw-r--r--sound/soc/s3c24xx/s3c24xx_simtec.h22
-rw-r--r--sound/soc/s3c24xx/s3c24xx_simtec_hermes.c153
-rw-r--r--sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c137
-rw-r--r--sound/soc/s3c24xx/s3c64xx-i2s.c19
-rw-r--r--sound/soc/s3c24xx/s3c64xx-i2s.h1
-rw-r--r--sound/soc/s3c24xx/smdk64xx_wm8580.c273
-rw-r--r--sound/soc/s6000/s6105-ipcam.c12
-rw-r--r--sound/soc/sh/Kconfig15
-rw-r--r--sound/soc/sh/Makefile4
-rw-r--r--sound/soc/sh/fsi-ak4642.c107
-rw-r--r--sound/soc/sh/fsi.c1004
-rw-r--r--sound/soc/soc-cache.c46
-rw-r--r--sound/soc/soc-core.c40
-rw-r--r--sound/soc/soc-dapm.c173
79 files changed, 4763 insertions, 335 deletions
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index 6c00ea45d5cb..4e34d19ddbc0 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -207,8 +207,8 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev)
207 snprintf(card->longname, sizeof(card->longname), 207 snprintf(card->longname, sizeof(card->longname),
208 "%s (%s)", dev->dev.driver->name, card->mixername); 208 "%s (%s)", dev->dev.driver->name, card->mixername);
209 209
210 if (pdata && pdata->codec_data) 210 if (pdata && pdata->codec_pdata[0])
211 snd_ac97_dev_add_pdata(ac97_bus->codec[0], pdata->codec_pdata); 211 snd_ac97_dev_add_pdata(ac97_bus->codec[0], pdata->codec_pdata[0]);
212 snd_card_set_dev(card, &dev->dev); 212 snd_card_set_dev(card, &dev->dev);
213 ret = snd_card_register(card); 213 ret = snd_card_register(card);
214 if (ret == 0) { 214 if (ret == 0) {
diff --git a/sound/arm/pxa2xx-pcm-lib.c b/sound/arm/pxa2xx-pcm-lib.c
index 6205f37d547c..743ac6a29065 100644
--- a/sound/arm/pxa2xx-pcm-lib.c
+++ b/sound/arm/pxa2xx-pcm-lib.c
@@ -136,6 +136,9 @@ int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
136{ 136{
137 struct pxa2xx_runtime_data *prtd = substream->runtime->private_data; 137 struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
138 138
139 if (!prtd || !prtd->params)
140 return 0;
141
139 DCSR(prtd->dma_ch) &= ~DCSR_RUN; 142 DCSR(prtd->dma_ch) &= ~DCSR_RUN;
140 DCSR(prtd->dma_ch) = 0; 143 DCSR(prtd->dma_ch) = 0;
141 DCMD(prtd->dma_ch) = 0; 144 DCMD(prtd->dma_ch) = 0;
diff --git a/sound/soc/atmel/playpaq_wm8510.c b/sound/soc/atmel/playpaq_wm8510.c
index 9eb610c2ba91..9df4c68ef000 100644
--- a/sound/soc/atmel/playpaq_wm8510.c
+++ b/sound/soc/atmel/playpaq_wm8510.c
@@ -268,7 +268,7 @@ static int playpaq_wm8510_hw_params(struct snd_pcm_substream *substream,
268#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */ 268#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */
269 269
270 270
271 ret = snd_soc_dai_set_pll(codec_dai, 0, 271 ret = snd_soc_dai_set_pll(codec_dai, 0, 0,
272 clk_get_rate(CODEC_CLK), pll_out); 272 clk_get_rate(CODEC_CLK), pll_out);
273 if (ret < 0) { 273 if (ret < 0) {
274 pr_warning("playpaq_wm8510: Failed to set CODEC DAI PLL (%d)\n", 274 pr_warning("playpaq_wm8510: Failed to set CODEC DAI PLL (%d)\n",
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c
index 479d7bdf1865..a521aa90ddee 100644
--- a/sound/soc/au1x/psc-ac97.c
+++ b/sound/soc/au1x/psc-ac97.c
@@ -1,8 +1,8 @@
1/* 1/*
2 * Au12x0/Au1550 PSC ALSA ASoC audio support. 2 * Au12x0/Au1550 PSC ALSA ASoC audio support.
3 * 3 *
4 * (c) 2007-2008 MSC Vertriebsges.m.b.H., 4 * (c) 2007-2009 MSC Vertriebsges.m.b.H.,
5 * Manuel Lauss <mano@roarinelk.homelinux.net> 5 * Manuel Lauss <manuel.lauss@gmail.com>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 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 8 * it under the terms of the GNU General Public License version 2 as
@@ -19,6 +19,7 @@
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/device.h> 20#include <linux/device.h>
21#include <linux/delay.h> 21#include <linux/delay.h>
22#include <linux/mutex.h>
22#include <linux/suspend.h> 23#include <linux/suspend.h>
23#include <sound/core.h> 24#include <sound/core.h>
24#include <sound/pcm.h> 25#include <sound/pcm.h>
@@ -29,6 +30,9 @@
29 30
30#include "psc.h" 31#include "psc.h"
31 32
33/* how often to retry failed codec register reads/writes */
34#define AC97_RW_RETRIES 5
35
32#define AC97_DIR \ 36#define AC97_DIR \
33 (SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE) 37 (SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
34 38
@@ -45,6 +49,9 @@
45#define AC97PCR_CLRFIFO(stype) \ 49#define AC97PCR_CLRFIFO(stype) \
46 ((stype) == PCM_TX ? PSC_AC97PCR_TC : PSC_AC97PCR_RC) 50 ((stype) == PCM_TX ? PSC_AC97PCR_TC : PSC_AC97PCR_RC)
47 51
52#define AC97STAT_BUSY(stype) \
53 ((stype) == PCM_TX ? PSC_AC97STAT_TB : PSC_AC97STAT_RB)
54
48/* instance data. There can be only one, MacLeod!!!! */ 55/* instance data. There can be only one, MacLeod!!!! */
49static struct au1xpsc_audio_data *au1xpsc_ac97_workdata; 56static struct au1xpsc_audio_data *au1xpsc_ac97_workdata;
50 57
@@ -54,24 +61,33 @@ static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97,
54{ 61{
55 /* FIXME */ 62 /* FIXME */
56 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; 63 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
57 unsigned short data, tmo; 64 unsigned short data, retry, tmo;
58 65
59 au_writel(PSC_AC97CDC_RD | PSC_AC97CDC_INDX(reg), AC97_CDC(pscdata)); 66 au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
60 au_sync(); 67 au_sync();
61 68
62 tmo = 1000; 69 retry = AC97_RW_RETRIES;
63 while ((!(au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)) && --tmo) 70 do {
64 udelay(2); 71 mutex_lock(&pscdata->lock);
72
73 au_writel(PSC_AC97CDC_RD | PSC_AC97CDC_INDX(reg),
74 AC97_CDC(pscdata));
75 au_sync();
76
77 tmo = 2000;
78 while ((!(au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD))
79 && --tmo)
80 udelay(2);
65 81
66 if (!tmo)
67 data = 0xffff;
68 else
69 data = au_readl(AC97_CDC(pscdata)) & 0xffff; 82 data = au_readl(AC97_CDC(pscdata)) & 0xffff;
70 83
71 au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata)); 84 au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
72 au_sync(); 85 au_sync();
86
87 mutex_unlock(&pscdata->lock);
88 } while (--retry && !tmo);
73 89
74 return data; 90 return retry ? data : 0xffff;
75} 91}
76 92
77/* AC97 controller writes to codec register */ 93/* AC97 controller writes to codec register */
@@ -80,16 +96,29 @@ static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
80{ 96{
81 /* FIXME */ 97 /* FIXME */
82 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; 98 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
83 unsigned int tmo; 99 unsigned int tmo, retry;
84 100
85 au_writel(PSC_AC97CDC_INDX(reg) | (val & 0xffff), AC97_CDC(pscdata)); 101 au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
86 au_sync(); 102 au_sync();
87 tmo = 1000; 103
88 while ((!(au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)) && --tmo) 104 retry = AC97_RW_RETRIES;
105 do {
106 mutex_lock(&pscdata->lock);
107
108 au_writel(PSC_AC97CDC_INDX(reg) | (val & 0xffff),
109 AC97_CDC(pscdata));
89 au_sync(); 110 au_sync();
90 111
91 au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata)); 112 tmo = 2000;
92 au_sync(); 113 while ((!(au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD))
114 && --tmo)
115 udelay(2);
116
117 au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
118 au_sync();
119
120 mutex_unlock(&pscdata->lock);
121 } while (--retry && !tmo);
93} 122}
94 123
95/* AC97 controller asserts a warm reset */ 124/* AC97 controller asserts a warm reset */
@@ -129,9 +158,9 @@ static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97)
129 au_sync(); 158 au_sync();
130 159
131 /* wait for PSC to indicate it's ready */ 160 /* wait for PSC to indicate it's ready */
132 i = 100000; 161 i = 1000;
133 while (!((au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_SR)) && (--i)) 162 while (!((au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_SR)) && (--i))
134 au_sync(); 163 msleep(1);
135 164
136 if (i == 0) { 165 if (i == 0) {
137 printk(KERN_ERR "au1xpsc-ac97: PSC not ready!\n"); 166 printk(KERN_ERR "au1xpsc-ac97: PSC not ready!\n");
@@ -143,9 +172,9 @@ static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97)
143 au_sync(); 172 au_sync();
144 173
145 /* wait for AC97 core to become ready */ 174 /* wait for AC97 core to become ready */
146 i = 100000; 175 i = 1000;
147 while (!((au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) && (--i)) 176 while (!((au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) && (--i))
148 au_sync(); 177 msleep(1);
149 if (i == 0) 178 if (i == 0)
150 printk(KERN_ERR "au1xpsc-ac97: AC97 ctrl not ready\n"); 179 printk(KERN_ERR "au1xpsc-ac97: AC97 ctrl not ready\n");
151} 180}
@@ -165,12 +194,12 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
165{ 194{
166 /* FIXME */ 195 /* FIXME */
167 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; 196 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
168 unsigned long r, stat; 197 unsigned long r, ro, stat;
169 int chans, stype = SUBSTREAM_TYPE(substream); 198 int chans, stype = SUBSTREAM_TYPE(substream);
170 199
171 chans = params_channels(params); 200 chans = params_channels(params);
172 201
173 r = au_readl(AC97_CFG(pscdata)); 202 r = ro = au_readl(AC97_CFG(pscdata));
174 stat = au_readl(AC97_STAT(pscdata)); 203 stat = au_readl(AC97_STAT(pscdata));
175 204
176 /* already active? */ 205 /* already active? */
@@ -180,9 +209,6 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
180 (pscdata->rate != params_rate(params))) 209 (pscdata->rate != params_rate(params)))
181 return -EINVAL; 210 return -EINVAL;
182 } else { 211 } else {
183 /* disable AC97 device controller first */
184 au_writel(r & ~PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
185 au_sync();
186 212
187 /* set sample bitdepth: REG[24:21]=(BITS-2)/2 */ 213 /* set sample bitdepth: REG[24:21]=(BITS-2)/2 */
188 r &= ~PSC_AC97CFG_LEN_MASK; 214 r &= ~PSC_AC97CFG_LEN_MASK;
@@ -199,14 +225,40 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
199 r |= PSC_AC97CFG_RXSLOT_ENA(4); 225 r |= PSC_AC97CFG_RXSLOT_ENA(4);
200 } 226 }
201 227
202 /* finally enable the AC97 controller again */ 228 /* do we need to poke the hardware? */
229 if (!(r ^ ro))
230 goto out;
231
232 /* ac97 engine is about to be disabled */
233 mutex_lock(&pscdata->lock);
234
235 /* disable AC97 device controller first... */
236 au_writel(r & ~PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
237 au_sync();
238
239 /* ...wait for it... */
240 while (au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)
241 asm volatile ("nop");
242
243 /* ...write config... */
244 au_writel(r, AC97_CFG(pscdata));
245 au_sync();
246
247 /* ...enable the AC97 controller again... */
203 au_writel(r | PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata)); 248 au_writel(r | PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
204 au_sync(); 249 au_sync();
205 250
251 /* ...and wait for ready bit */
252 while (!(au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR))
253 asm volatile ("nop");
254
255 mutex_unlock(&pscdata->lock);
256
206 pscdata->cfg = r; 257 pscdata->cfg = r;
207 pscdata->rate = params_rate(params); 258 pscdata->rate = params_rate(params);
208 } 259 }
209 260
261out:
210 return 0; 262 return 0;
211} 263}
212 264
@@ -222,6 +274,8 @@ static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
222 switch (cmd) { 274 switch (cmd) {
223 case SNDRV_PCM_TRIGGER_START: 275 case SNDRV_PCM_TRIGGER_START:
224 case SNDRV_PCM_TRIGGER_RESUME: 276 case SNDRV_PCM_TRIGGER_RESUME:
277 au_writel(AC97PCR_CLRFIFO(stype), AC97_PCR(pscdata));
278 au_sync();
225 au_writel(AC97PCR_START(stype), AC97_PCR(pscdata)); 279 au_writel(AC97PCR_START(stype), AC97_PCR(pscdata));
226 au_sync(); 280 au_sync();
227 break; 281 break;
@@ -229,6 +283,13 @@ static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
229 case SNDRV_PCM_TRIGGER_SUSPEND: 283 case SNDRV_PCM_TRIGGER_SUSPEND:
230 au_writel(AC97PCR_STOP(stype), AC97_PCR(pscdata)); 284 au_writel(AC97PCR_STOP(stype), AC97_PCR(pscdata));
231 au_sync(); 285 au_sync();
286
287 while (au_readl(AC97_STAT(pscdata)) & AC97STAT_BUSY(stype))
288 asm volatile ("nop");
289
290 au_writel(AC97PCR_CLRFIFO(stype), AC97_PCR(pscdata));
291 au_sync();
292
232 break; 293 break;
233 default: 294 default:
234 ret = -EINVAL; 295 ret = -EINVAL;
@@ -251,6 +312,8 @@ static int au1xpsc_ac97_probe(struct platform_device *pdev,
251 if (!au1xpsc_ac97_workdata) 312 if (!au1xpsc_ac97_workdata)
252 return -ENOMEM; 313 return -ENOMEM;
253 314
315 mutex_init(&au1xpsc_ac97_workdata->lock);
316
254 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 317 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
255 if (!r) { 318 if (!r) {
256 ret = -ENODEV; 319 ret = -ENODEV;
@@ -269,9 +332,9 @@ static int au1xpsc_ac97_probe(struct platform_device *pdev,
269 goto out1; 332 goto out1;
270 333
271 /* configuration: max dma trigger threshold, enable ac97 */ 334 /* configuration: max dma trigger threshold, enable ac97 */
272 au1xpsc_ac97_workdata->cfg = PSC_AC97CFG_RT_FIFO8 | 335 au1xpsc_ac97_workdata->cfg = PSC_AC97CFG_RT_FIFO8 |
273 PSC_AC97CFG_TT_FIFO8 | 336 PSC_AC97CFG_TT_FIFO8 |
274 PSC_AC97CFG_DE_ENABLE; 337 PSC_AC97CFG_DE_ENABLE;
275 338
276 /* preserve PSC clock source set up by platform (dev.platform_data 339 /* preserve PSC clock source set up by platform (dev.platform_data
277 * is already occupied by soc layer) 340 * is already occupied by soc layer)
@@ -386,4 +449,4 @@ module_exit(au1xpsc_ac97_exit);
386 449
387MODULE_LICENSE("GPL"); 450MODULE_LICENSE("GPL");
388MODULE_DESCRIPTION("Au12x0/Au1550 PSC AC97 ALSA ASoC audio driver"); 451MODULE_DESCRIPTION("Au12x0/Au1550 PSC AC97 ALSA ASoC audio driver");
389MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>"); 452MODULE_AUTHOR("Manuel Lauss <manuel.lauss@gmail.com>");
diff --git a/sound/soc/au1x/psc.h b/sound/soc/au1x/psc.h
index 8fdb1a04a07b..3f474e8ed4f6 100644
--- a/sound/soc/au1x/psc.h
+++ b/sound/soc/au1x/psc.h
@@ -29,6 +29,7 @@ struct au1xpsc_audio_data {
29 29
30 unsigned long pm[2]; 30 unsigned long pm[2];
31 struct resource *ioarea; 31 struct resource *ioarea;
32 struct mutex lock;
32}; 33};
33 34
34#define PCM_TX 0 35#define PCM_TX 0
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig
index 8a4de4de30f2..ac927ffdc961 100644
--- a/sound/soc/blackfin/Kconfig
+++ b/sound/soc/blackfin/Kconfig
@@ -88,6 +88,14 @@ config SND_BF5XX_SOC_AC97
88 select SND_SOC_AC97_BUS 88 select SND_SOC_AC97_BUS
89 select SND_BF5XX_SOC_SPORT 89 select SND_BF5XX_SOC_SPORT
90 90
91config SND_BF5XX_SOC_AD1836
92 tristate "SoC AD1836 Audio support for BF5xx"
93 depends on SND_BF5XX_TDM
94 select SND_BF5XX_SOC_TDM
95 select SND_SOC_AD1836
96 help
97 Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT.
98
91config SND_BF5XX_SOC_AD1980 99config SND_BF5XX_SOC_AD1980
92 tristate "SoC AD1980/1 Audio support for BF5xx" 100 tristate "SoC AD1980/1 Audio support for BF5xx"
93 depends on SND_BF5XX_AC97 101 depends on SND_BF5XX_AC97
diff --git a/sound/soc/blackfin/Makefile b/sound/soc/blackfin/Makefile
index f4d760741fab..87e30423912f 100644
--- a/sound/soc/blackfin/Makefile
+++ b/sound/soc/blackfin/Makefile
@@ -16,11 +16,13 @@ obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o
16obj-$(CONFIG_SND_BF5XX_SOC_TDM) += snd-soc-bf5xx-tdm.o 16obj-$(CONFIG_SND_BF5XX_SOC_TDM) += snd-soc-bf5xx-tdm.o
17 17
18# Blackfin Machine Support 18# Blackfin Machine Support
19snd-ad1836-objs := bf5xx-ad1836.o
19snd-ad1980-objs := bf5xx-ad1980.o 20snd-ad1980-objs := bf5xx-ad1980.o
20snd-ssm2602-objs := bf5xx-ssm2602.o 21snd-ssm2602-objs := bf5xx-ssm2602.o
21snd-ad73311-objs := bf5xx-ad73311.o 22snd-ad73311-objs := bf5xx-ad73311.o
22snd-ad1938-objs := bf5xx-ad1938.o 23snd-ad1938-objs := bf5xx-ad1938.o
23 24
25obj-$(CONFIG_SND_BF5XX_SOC_AD1836) += snd-ad1836.o
24obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o 26obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o
25obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o 27obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o
26obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o 28obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c
index 2758b9017a7f..e69322978739 100644
--- a/sound/soc/blackfin/bf5xx-ac97.c
+++ b/sound/soc/blackfin/bf5xx-ac97.c
@@ -277,7 +277,11 @@ static int bf5xx_ac97_resume(struct snd_soc_dai *dai)
277 if (!dai->active) 277 if (!dai->active)
278 return 0; 278 return 0;
279 279
280#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT)
281 ret = sport_set_multichannel(sport, 16, 0x3FF, 1);
282#else
280 ret = sport_set_multichannel(sport, 16, 0x1F, 1); 283 ret = sport_set_multichannel(sport, 16, 0x1F, 1);
284#endif
281 if (ret) { 285 if (ret) {
282 pr_err("SPORT is busy!\n"); 286 pr_err("SPORT is busy!\n");
283 return -EBUSY; 287 return -EBUSY;
@@ -334,7 +338,11 @@ static int bf5xx_ac97_probe(struct platform_device *pdev,
334 goto sport_err; 338 goto sport_err;
335 } 339 }
336 /*SPORT works in TDM mode to simulate AC97 transfers*/ 340 /*SPORT works in TDM mode to simulate AC97 transfers*/
341#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT)
342 ret = sport_set_multichannel(sport_handle, 16, 0x3FF, 1);
343#else
337 ret = sport_set_multichannel(sport_handle, 16, 0x1F, 1); 344 ret = sport_set_multichannel(sport_handle, 16, 0x1F, 1);
345#endif
338 if (ret) { 346 if (ret) {
339 pr_err("SPORT is busy!\n"); 347 pr_err("SPORT is busy!\n");
340 ret = -EBUSY; 348 ret = -EBUSY;
diff --git a/sound/soc/blackfin/bf5xx-ac97.h b/sound/soc/blackfin/bf5xx-ac97.h
index 3f2a911fe0cb..a1f97dd809d6 100644
--- a/sound/soc/blackfin/bf5xx-ac97.h
+++ b/sound/soc/blackfin/bf5xx-ac97.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/sound/arm/bf5xx-ac97.h 2 * sound/soc/blackfin/bf5xx-ac97.h
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify 4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as 5 * it under the terms of the GNU General Public License version 2 as
diff --git a/sound/soc/blackfin/bf5xx-ad1836.c b/sound/soc/blackfin/bf5xx-ad1836.c
new file mode 100644
index 000000000000..0f45a3f56be8
--- /dev/null
+++ b/sound/soc/blackfin/bf5xx-ad1836.c
@@ -0,0 +1,135 @@
1/*
2 * File: sound/soc/blackfin/bf5xx-ad1836.c
3 * Author: Barry Song <Barry.Song@analog.com>
4 *
5 * Created: Aug 4 2009
6 * Description: Board driver for ad1836 sound chip
7 *
8 * Bugs: Enter bugs at http://blackfin.uclinux.org/
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 */
16
17#include <linux/module.h>
18#include <linux/moduleparam.h>
19#include <linux/device.h>
20#include <sound/core.h>
21#include <sound/pcm.h>
22#include <sound/soc.h>
23#include <sound/soc-dapm.h>
24#include <sound/pcm_params.h>
25
26#include <asm/blackfin.h>
27#include <asm/cacheflush.h>
28#include <asm/irq.h>
29#include <asm/dma.h>
30#include <asm/portmux.h>
31
32#include "../codecs/ad1836.h"
33#include "bf5xx-sport.h"
34
35#include "bf5xx-tdm-pcm.h"
36#include "bf5xx-tdm.h"
37
38static struct snd_soc_card bf5xx_ad1836;
39
40static int bf5xx_ad1836_startup(struct snd_pcm_substream *substream)
41{
42 struct snd_soc_pcm_runtime *rtd = substream->private_data;
43 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
44
45 cpu_dai->private_data = sport_handle;
46 return 0;
47}
48
49static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream,
50 struct snd_pcm_hw_params *params)
51{
52 struct snd_soc_pcm_runtime *rtd = substream->private_data;
53 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
54 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
55 unsigned int channel_map[] = {0, 4, 1, 5, 2, 6, 3, 7};
56 int ret = 0;
57 /* set cpu DAI configuration */
58 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
59 SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
60 if (ret < 0)
61 return ret;
62
63 /* set codec DAI configuration */
64 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |
65 SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
66 if (ret < 0)
67 return ret;
68
69 /* set cpu DAI channel mapping */
70 ret = snd_soc_dai_set_channel_map(cpu_dai, ARRAY_SIZE(channel_map),
71 channel_map, ARRAY_SIZE(channel_map), channel_map);
72 if (ret < 0)
73 return ret;
74
75 return 0;
76}
77
78static struct snd_soc_ops bf5xx_ad1836_ops = {
79 .startup = bf5xx_ad1836_startup,
80 .hw_params = bf5xx_ad1836_hw_params,
81};
82
83static struct snd_soc_dai_link bf5xx_ad1836_dai = {
84 .name = "ad1836",
85 .stream_name = "AD1836",
86 .cpu_dai = &bf5xx_tdm_dai,
87 .codec_dai = &ad1836_dai,
88 .ops = &bf5xx_ad1836_ops,
89};
90
91static struct snd_soc_card bf5xx_ad1836 = {
92 .name = "bf5xx_ad1836",
93 .platform = &bf5xx_tdm_soc_platform,
94 .dai_link = &bf5xx_ad1836_dai,
95 .num_links = 1,
96};
97
98static struct snd_soc_device bf5xx_ad1836_snd_devdata = {
99 .card = &bf5xx_ad1836,
100 .codec_dev = &soc_codec_dev_ad1836,
101};
102
103static struct platform_device *bfxx_ad1836_snd_device;
104
105static int __init bf5xx_ad1836_init(void)
106{
107 int ret;
108
109 bfxx_ad1836_snd_device = platform_device_alloc("soc-audio", -1);
110 if (!bfxx_ad1836_snd_device)
111 return -ENOMEM;
112
113 platform_set_drvdata(bfxx_ad1836_snd_device, &bf5xx_ad1836_snd_devdata);
114 bf5xx_ad1836_snd_devdata.dev = &bfxx_ad1836_snd_device->dev;
115 ret = platform_device_add(bfxx_ad1836_snd_device);
116
117 if (ret)
118 platform_device_put(bfxx_ad1836_snd_device);
119
120 return ret;
121}
122
123static void __exit bf5xx_ad1836_exit(void)
124{
125 platform_device_unregister(bfxx_ad1836_snd_device);
126}
127
128module_init(bf5xx_ad1836_init);
129module_exit(bf5xx_ad1836_exit);
130
131/* Module information */
132MODULE_AUTHOR("Barry Song");
133MODULE_DESCRIPTION("ALSA SoC AD1836 board driver");
134MODULE_LICENSE("GPL");
135
diff --git a/sound/soc/blackfin/bf5xx-ad1938.c b/sound/soc/blackfin/bf5xx-ad1938.c
index 08269e91810c..2ef1e5013b8c 100644
--- a/sound/soc/blackfin/bf5xx-ad1938.c
+++ b/sound/soc/blackfin/bf5xx-ad1938.c
@@ -61,6 +61,7 @@ static int bf5xx_ad1938_hw_params(struct snd_pcm_substream *substream,
61 struct snd_soc_pcm_runtime *rtd = substream->private_data; 61 struct snd_soc_pcm_runtime *rtd = substream->private_data;
62 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 62 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
63 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 63 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
64 unsigned int channel_map[] = {0, 1, 2, 3, 4, 5, 6, 7};
64 int ret = 0; 65 int ret = 0;
65 /* set cpu DAI configuration */ 66 /* set cpu DAI configuration */
66 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | 67 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
@@ -75,7 +76,13 @@ static int bf5xx_ad1938_hw_params(struct snd_pcm_substream *substream,
75 return ret; 76 return ret;
76 77
77 /* set codec DAI slots, 8 channels, all channels are enabled */ 78 /* set codec DAI slots, 8 channels, all channels are enabled */
78 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xFF, 8); 79 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xFF, 0xFF, 8, 32);
80 if (ret < 0)
81 return ret;
82
83 /* set cpu DAI channel mapping */
84 ret = snd_soc_dai_set_channel_map(cpu_dai, ARRAY_SIZE(channel_map),
85 channel_map, ARRAY_SIZE(channel_map), channel_map);
79 if (ret < 0) 86 if (ret < 0)
80 return ret; 87 return ret;
81 88
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c
index 876abade27e1..1e9d161c76c4 100644
--- a/sound/soc/blackfin/bf5xx-i2s.c
+++ b/sound/soc/blackfin/bf5xx-i2s.c
@@ -227,7 +227,8 @@ static int bf5xx_i2s_probe(struct platform_device *pdev,
227 return 0; 227 return 0;
228} 228}
229 229
230static void bf5xx_i2s_remove(struct snd_soc_dai *dai) 230static void bf5xx_i2s_remove(struct platform_device *pdev,
231 struct snd_soc_dai *dai)
231{ 232{
232 pr_debug("%s enter\n", __func__); 233 pr_debug("%s enter\n", __func__);
233 peripheral_free_list(&sport_req[sport_num][0]); 234 peripheral_free_list(&sport_req[sport_num][0]);
@@ -236,36 +237,31 @@ static void bf5xx_i2s_remove(struct snd_soc_dai *dai)
236#ifdef CONFIG_PM 237#ifdef CONFIG_PM
237static int bf5xx_i2s_suspend(struct snd_soc_dai *dai) 238static int bf5xx_i2s_suspend(struct snd_soc_dai *dai)
238{ 239{
239 struct sport_device *sport =
240 (struct sport_device *)dai->private_data;
241 240
242 pr_debug("%s : sport %d\n", __func__, dai->id); 241 pr_debug("%s : sport %d\n", __func__, dai->id);
243 if (!dai->active) 242
244 return 0;
245 if (dai->capture.active) 243 if (dai->capture.active)
246 sport_rx_stop(sport); 244 sport_rx_stop(sport_handle);
247 if (dai->playback.active) 245 if (dai->playback.active)
248 sport_tx_stop(sport); 246 sport_tx_stop(sport_handle);
249 return 0; 247 return 0;
250} 248}
251 249
252static int bf5xx_i2s_resume(struct snd_soc_dai *dai) 250static int bf5xx_i2s_resume(struct snd_soc_dai *dai)
253{ 251{
254 int ret; 252 int ret;
255 struct sport_device *sport =
256 (struct sport_device *)dai->private_data;
257 253
258 pr_debug("%s : sport %d\n", __func__, dai->id); 254 pr_debug("%s : sport %d\n", __func__, dai->id);
259 if (!dai->active)
260 return 0;
261 255
262 ret = sport_config_rx(sport, RFSR | RCKFE, RSFSE|0x1f, 0, 0); 256 ret = sport_config_rx(sport_handle, bf5xx_i2s.rcr1,
257 bf5xx_i2s.rcr2, 0, 0);
263 if (ret) { 258 if (ret) {
264 pr_err("SPORT is busy!\n"); 259 pr_err("SPORT is busy!\n");
265 return -EBUSY; 260 return -EBUSY;
266 } 261 }
267 262
268 ret = sport_config_tx(sport, TFSR | TCKFE, TSFSE|0x1f, 0, 0); 263 ret = sport_config_tx(sport_handle, bf5xx_i2s.tcr1,
264 bf5xx_i2s.tcr2, 0, 0);
269 if (ret) { 265 if (ret) {
270 pr_err("SPORT is busy!\n"); 266 pr_err("SPORT is busy!\n");
271 return -EBUSY; 267 return -EBUSY;
diff --git a/sound/soc/blackfin/bf5xx-i2s.h b/sound/soc/blackfin/bf5xx-i2s.h
index 7107d1a0b06b..264ecdcba35a 100644
--- a/sound/soc/blackfin/bf5xx-i2s.h
+++ b/sound/soc/blackfin/bf5xx-i2s.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/sound/arm/bf5xx-i2s.h 2 * sound/soc/blackfin/bf5xx-i2s.h
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify 4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as 5 * it under the terms of the GNU General Public License version 2 as
diff --git a/sound/soc/blackfin/bf5xx-sport.c b/sound/soc/blackfin/bf5xx-sport.c
index 469ce7fab20c..99051ff0954e 100644
--- a/sound/soc/blackfin/bf5xx-sport.c
+++ b/sound/soc/blackfin/bf5xx-sport.c
@@ -326,7 +326,7 @@ static inline int sport_hook_tx_dummy(struct sport_device *sport)
326 326
327int sport_tx_start(struct sport_device *sport) 327int sport_tx_start(struct sport_device *sport)
328{ 328{
329 unsigned flags; 329 unsigned long flags;
330 pr_debug("%s: tx_run:%d, rx_run:%d\n", __func__, 330 pr_debug("%s: tx_run:%d, rx_run:%d\n", __func__,
331 sport->tx_run, sport->rx_run); 331 sport->tx_run, sport->rx_run);
332 if (sport->tx_run) 332 if (sport->tx_run)
diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.c b/sound/soc/blackfin/bf5xx-tdm-pcm.c
index ccb5e823bd18..a8c73cbbd685 100644
--- a/sound/soc/blackfin/bf5xx-tdm-pcm.c
+++ b/sound/soc/blackfin/bf5xx-tdm-pcm.c
@@ -43,7 +43,7 @@
43#include "bf5xx-tdm.h" 43#include "bf5xx-tdm.h"
44#include "bf5xx-sport.h" 44#include "bf5xx-sport.h"
45 45
46#define PCM_BUFFER_MAX 0x10000 46#define PCM_BUFFER_MAX 0x8000
47#define FRAGMENT_SIZE_MIN (4*1024) 47#define FRAGMENT_SIZE_MIN (4*1024)
48#define FRAGMENTS_MIN 2 48#define FRAGMENTS_MIN 2
49#define FRAGMENTS_MAX 32 49#define FRAGMENTS_MAX 32
@@ -177,6 +177,9 @@ out:
177static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel, 177static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
178 snd_pcm_uframes_t pos, void *buf, snd_pcm_uframes_t count) 178 snd_pcm_uframes_t pos, void *buf, snd_pcm_uframes_t count)
179{ 179{
180 struct snd_pcm_runtime *runtime = substream->runtime;
181 struct sport_device *sport = runtime->private_data;
182 struct bf5xx_tdm_port *tdm_port = sport->private_data;
180 unsigned int *src; 183 unsigned int *src;
181 unsigned int *dst; 184 unsigned int *dst;
182 int i; 185 int i;
@@ -188,7 +191,7 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
188 dst += pos * 8; 191 dst += pos * 8;
189 while (count--) { 192 while (count--) {
190 for (i = 0; i < substream->runtime->channels; i++) 193 for (i = 0; i < substream->runtime->channels; i++)
191 *(dst + i) = *src++; 194 *(dst + tdm_port->tx_map[i]) = *src++;
192 dst += 8; 195 dst += 8;
193 } 196 }
194 } else { 197 } else {
@@ -198,7 +201,7 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
198 src += pos * 8; 201 src += pos * 8;
199 while (count--) { 202 while (count--) {
200 for (i = 0; i < substream->runtime->channels; i++) 203 for (i = 0; i < substream->runtime->channels; i++)
201 *dst++ = *(src+i); 204 *dst++ = *(src + tdm_port->rx_map[i]);
202 src += 8; 205 src += 8;
203 } 206 }
204 } 207 }
diff --git a/sound/soc/blackfin/bf5xx-tdm.c b/sound/soc/blackfin/bf5xx-tdm.c
index 3096badf09a5..600987d8a871 100644
--- a/sound/soc/blackfin/bf5xx-tdm.c
+++ b/sound/soc/blackfin/bf5xx-tdm.c
@@ -46,14 +46,6 @@
46#include "bf5xx-sport.h" 46#include "bf5xx-sport.h"
47#include "bf5xx-tdm.h" 47#include "bf5xx-tdm.h"
48 48
49struct bf5xx_tdm_port {
50 u16 tcr1;
51 u16 rcr1;
52 u16 tcr2;
53 u16 rcr2;
54 int configured;
55};
56
57static struct bf5xx_tdm_port bf5xx_tdm; 49static struct bf5xx_tdm_port bf5xx_tdm;
58static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM; 50static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM;
59 51
@@ -181,6 +173,40 @@ static void bf5xx_tdm_shutdown(struct snd_pcm_substream *substream,
181 bf5xx_tdm.configured = 0; 173 bf5xx_tdm.configured = 0;
182} 174}
183 175
176static int bf5xx_tdm_set_channel_map(struct snd_soc_dai *dai,
177 unsigned int tx_num, unsigned int *tx_slot,
178 unsigned int rx_num, unsigned int *rx_slot)
179{
180 int i;
181 unsigned int slot;
182 unsigned int tx_mapped = 0, rx_mapped = 0;
183
184 if ((tx_num > BFIN_TDM_DAI_MAX_SLOTS) ||
185 (rx_num > BFIN_TDM_DAI_MAX_SLOTS))
186 return -EINVAL;
187
188 for (i = 0; i < tx_num; i++) {
189 slot = tx_slot[i];
190 if ((slot < BFIN_TDM_DAI_MAX_SLOTS) &&
191 (!(tx_mapped & (1 << slot)))) {
192 bf5xx_tdm.tx_map[i] = slot;
193 tx_mapped |= 1 << slot;
194 } else
195 return -EINVAL;
196 }
197 for (i = 0; i < rx_num; i++) {
198 slot = rx_slot[i];
199 if ((slot < BFIN_TDM_DAI_MAX_SLOTS) &&
200 (!(rx_mapped & (1 << slot)))) {
201 bf5xx_tdm.rx_map[i] = slot;
202 rx_mapped |= 1 << slot;
203 } else
204 return -EINVAL;
205 }
206
207 return 0;
208}
209
184#ifdef CONFIG_PM 210#ifdef CONFIG_PM
185static int bf5xx_tdm_suspend(struct snd_soc_dai *dai) 211static int bf5xx_tdm_suspend(struct snd_soc_dai *dai)
186{ 212{
@@ -235,6 +261,7 @@ static struct snd_soc_dai_ops bf5xx_tdm_dai_ops = {
235 .hw_params = bf5xx_tdm_hw_params, 261 .hw_params = bf5xx_tdm_hw_params,
236 .set_fmt = bf5xx_tdm_set_dai_fmt, 262 .set_fmt = bf5xx_tdm_set_dai_fmt,
237 .shutdown = bf5xx_tdm_shutdown, 263 .shutdown = bf5xx_tdm_shutdown,
264 .set_channel_map = bf5xx_tdm_set_channel_map,
238}; 265};
239 266
240struct snd_soc_dai bf5xx_tdm_dai = { 267struct snd_soc_dai bf5xx_tdm_dai = {
@@ -300,6 +327,8 @@ static int __devinit bfin_tdm_probe(struct platform_device *pdev)
300 pr_err("Failed to register DAI: %d\n", ret); 327 pr_err("Failed to register DAI: %d\n", ret);
301 goto sport_config_err; 328 goto sport_config_err;
302 } 329 }
330
331 sport_handle->private_data = &bf5xx_tdm;
303 return 0; 332 return 0;
304 333
305sport_config_err: 334sport_config_err:
diff --git a/sound/soc/blackfin/bf5xx-tdm.h b/sound/soc/blackfin/bf5xx-tdm.h
index 618ec3d90cd4..04189a18c1ba 100644
--- a/sound/soc/blackfin/bf5xx-tdm.h
+++ b/sound/soc/blackfin/bf5xx-tdm.h
@@ -9,6 +9,17 @@
9#ifndef _BF5XX_TDM_H 9#ifndef _BF5XX_TDM_H
10#define _BF5XX_TDM_H 10#define _BF5XX_TDM_H
11 11
12#define BFIN_TDM_DAI_MAX_SLOTS 8
13struct bf5xx_tdm_port {
14 u16 tcr1;
15 u16 rcr1;
16 u16 tcr2;
17 u16 rcr2;
18 unsigned int tx_map[BFIN_TDM_DAI_MAX_SLOTS];
19 unsigned int rx_map[BFIN_TDM_DAI_MAX_SLOTS];
20 int configured;
21};
22
12extern struct snd_soc_dai bf5xx_tdm_dai; 23extern struct snd_soc_dai bf5xx_tdm_dai;
13 24
14#endif 25#endif
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 20ebf7437f98..3c46f34928ec 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -18,6 +18,8 @@ config SND_SOC_ALL_CODECS
18 select SND_SOC_AD73311 if I2C 18 select SND_SOC_AD73311 if I2C
19 select SND_SOC_AK4104 if SPI_MASTER 19 select SND_SOC_AK4104 if SPI_MASTER
20 select SND_SOC_AK4535 if I2C 20 select SND_SOC_AK4535 if I2C
21 select SND_SOC_AK4642 if I2C
22 select SND_SOC_AK4671 if I2C
21 select SND_SOC_CS4270 if I2C 23 select SND_SOC_CS4270 if I2C
22 select SND_SOC_MAX9877 if I2C 24 select SND_SOC_MAX9877 if I2C
23 select SND_SOC_PCM3008 25 select SND_SOC_PCM3008
@@ -93,6 +95,12 @@ config SND_SOC_AK4104
93config SND_SOC_AK4535 95config SND_SOC_AK4535
94 tristate 96 tristate
95 97
98config SND_SOC_AK4642
99 tristate
100
101config SND_SOC_AK4671
102 tristate
103
96# Cirrus Logic CS4270 Codec 104# Cirrus Logic CS4270 Codec
97config SND_SOC_CS4270 105config SND_SOC_CS4270
98 tristate 106 tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 711d8f5887de..fc1c458cbe2f 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -5,6 +5,8 @@ snd-soc-ad1980-objs := ad1980.o
5snd-soc-ad73311-objs := ad73311.o 5snd-soc-ad73311-objs := ad73311.o
6snd-soc-ak4104-objs := ak4104.o 6snd-soc-ak4104-objs := ak4104.o
7snd-soc-ak4535-objs := ak4535.o 7snd-soc-ak4535-objs := ak4535.o
8snd-soc-ak4642-objs := ak4642.o
9snd-soc-ak4671-objs := ak4671.o
8snd-soc-cs4270-objs := cs4270.o 10snd-soc-cs4270-objs := cs4270.o
9snd-soc-cx20442-objs := cx20442.o 11snd-soc-cx20442-objs := cx20442.o
10snd-soc-l3-objs := l3.o 12snd-soc-l3-objs := l3.o
@@ -55,6 +57,8 @@ obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o
55obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o 57obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
56obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o 58obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o
57obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o 59obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o
60obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o
61obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o
58obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o 62obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
59obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o 63obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
60obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o 64obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c
index 3612bb92df90..01343dc984fd 100644
--- a/sound/soc/codecs/ad1836.c
+++ b/sound/soc/codecs/ad1836.c
@@ -18,7 +18,6 @@
18 18
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/version.h>
22#include <linux/kernel.h> 21#include <linux/kernel.h>
23#include <linux/device.h> 22#include <linux/device.h>
24#include <sound/core.h> 23#include <sound/core.h>
diff --git a/sound/soc/codecs/ad1938.c b/sound/soc/codecs/ad1938.c
index e62b27701a49..9a049a1995a3 100644
--- a/sound/soc/codecs/ad1938.c
+++ b/sound/soc/codecs/ad1938.c
@@ -28,7 +28,6 @@
28 28
29#include <linux/init.h> 29#include <linux/init.h>
30#include <linux/module.h> 30#include <linux/module.h>
31#include <linux/version.h>
32#include <linux/kernel.h> 31#include <linux/kernel.h>
33#include <linux/device.h> 32#include <linux/device.h>
34#include <sound/core.h> 33#include <sound/core.h>
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
new file mode 100644
index 000000000000..e057c7b578df
--- /dev/null
+++ b/sound/soc/codecs/ak4642.c
@@ -0,0 +1,502 @@
1/*
2 * ak4642.c -- AK4642/AK4643 ALSA Soc Audio driver
3 *
4 * Copyright (C) 2009 Renesas Solutions Corp.
5 * Kuninori Morimoto <morimoto.kuninori@renesas.com>
6 *
7 * Based on wm8731.c by Richard Purdie
8 * Based on ak4535.c by Richard Purdie
9 * Based on wm8753.c by Liam Girdwood
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15
16/* ** CAUTION **
17 *
18 * This is very simple driver.
19 * It can use headphone output / stereo input only
20 *
21 * AK4642 is not tested.
22 * AK4643 is tested.
23 */
24
25#include <linux/module.h>
26#include <linux/moduleparam.h>
27#include <linux/init.h>
28#include <linux/delay.h>
29#include <linux/pm.h>
30#include <linux/i2c.h>
31#include <linux/platform_device.h>
32#include <sound/core.h>
33#include <sound/pcm.h>
34#include <sound/pcm_params.h>
35#include <sound/soc.h>
36#include <sound/soc-dapm.h>
37#include <sound/initval.h>
38
39#include "ak4642.h"
40
41#define AK4642_VERSION "0.0.1"
42
43#define PW_MGMT1 0x00
44#define PW_MGMT2 0x01
45#define SG_SL1 0x02
46#define SG_SL2 0x03
47#define MD_CTL1 0x04
48#define MD_CTL2 0x05
49#define TIMER 0x06
50#define ALC_CTL1 0x07
51#define ALC_CTL2 0x08
52#define L_IVC 0x09
53#define L_DVC 0x0a
54#define ALC_CTL3 0x0b
55#define R_IVC 0x0c
56#define R_DVC 0x0d
57#define MD_CTL3 0x0e
58#define MD_CTL4 0x0f
59#define PW_MGMT3 0x10
60#define DF_S 0x11
61#define FIL3_0 0x12
62#define FIL3_1 0x13
63#define FIL3_2 0x14
64#define FIL3_3 0x15
65#define EQ_0 0x16
66#define EQ_1 0x17
67#define EQ_2 0x18
68#define EQ_3 0x19
69#define EQ_4 0x1a
70#define EQ_5 0x1b
71#define FIL1_0 0x1c
72#define FIL1_1 0x1d
73#define FIL1_2 0x1e
74#define FIL1_3 0x1f
75#define PW_MGMT4 0x20
76#define MD_CTL5 0x21
77#define LO_MS 0x22
78#define HP_MS 0x23
79#define SPK_MS 0x24
80
81#define AK4642_CACHEREGNUM 0x25
82
83struct snd_soc_codec_device soc_codec_dev_ak4642;
84
85/* codec private data */
86struct ak4642_priv {
87 struct snd_soc_codec codec;
88 unsigned int sysclk;
89};
90
91static struct snd_soc_codec *ak4642_codec;
92
93/*
94 * ak4642 register cache
95 */
96static const u16 ak4642_reg[AK4642_CACHEREGNUM] = {
97 0x0000, 0x0000, 0x0001, 0x0000,
98 0x0002, 0x0000, 0x0000, 0x0000,
99 0x00e1, 0x00e1, 0x0018, 0x0000,
100 0x00e1, 0x0018, 0x0011, 0x0008,
101 0x0000, 0x0000, 0x0000, 0x0000,
102 0x0000, 0x0000, 0x0000, 0x0000,
103 0x0000, 0x0000, 0x0000, 0x0000,
104 0x0000, 0x0000, 0x0000, 0x0000,
105 0x0000, 0x0000, 0x0000, 0x0000,
106 0x0000,
107};
108
109/*
110 * read ak4642 register cache
111 */
112static inline unsigned int ak4642_read_reg_cache(struct snd_soc_codec *codec,
113 unsigned int reg)
114{
115 u16 *cache = codec->reg_cache;
116 if (reg >= AK4642_CACHEREGNUM)
117 return -1;
118 return cache[reg];
119}
120
121/*
122 * write ak4642 register cache
123 */
124static inline void ak4642_write_reg_cache(struct snd_soc_codec *codec,
125 u16 reg, unsigned int value)
126{
127 u16 *cache = codec->reg_cache;
128 if (reg >= AK4642_CACHEREGNUM)
129 return;
130
131 cache[reg] = value;
132}
133
134/*
135 * write to the AK4642 register space
136 */
137static int ak4642_write(struct snd_soc_codec *codec, unsigned int reg,
138 unsigned int value)
139{
140 u8 data[2];
141
142 /* data is
143 * D15..D8 AK4642 register offset
144 * D7...D0 register data
145 */
146 data[0] = reg & 0xff;
147 data[1] = value & 0xff;
148
149 if (codec->hw_write(codec->control_data, data, 2) == 2) {
150 ak4642_write_reg_cache(codec, reg, value);
151 return 0;
152 } else
153 return -EIO;
154}
155
156static int ak4642_sync(struct snd_soc_codec *codec)
157{
158 u16 *cache = codec->reg_cache;
159 int i, r = 0;
160
161 for (i = 0; i < AK4642_CACHEREGNUM; i++)
162 r |= ak4642_write(codec, i, cache[i]);
163
164 return r;
165};
166
167static int ak4642_dai_startup(struct snd_pcm_substream *substream,
168 struct snd_soc_dai *dai)
169{
170 int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
171 struct snd_soc_codec *codec = dai->codec;
172
173 if (is_play) {
174 /*
175 * start headphone output
176 *
177 * PLL, Master Mode
178 * Audio I/F Format :MSB justified (ADC & DAC)
179 * Sampling Frequency: 44.1kHz
180 * Digital Volume: −8dB
181 * Bass Boost Level : Middle
182 *
183 * This operation came from example code of
184 * "ASAHI KASEI AK4642" (japanese) manual p97.
185 *
186 * Example code use 0x39, 0x79 value for 0x01 address,
187 * But we need MCKO (0x02) bit now
188 */
189 ak4642_write(codec, 0x05, 0x27);
190 ak4642_write(codec, 0x0f, 0x09);
191 ak4642_write(codec, 0x0e, 0x19);
192 ak4642_write(codec, 0x09, 0x91);
193 ak4642_write(codec, 0x0c, 0x91);
194 ak4642_write(codec, 0x0a, 0x28);
195 ak4642_write(codec, 0x0d, 0x28);
196 ak4642_write(codec, 0x00, 0x64);
197 ak4642_write(codec, 0x01, 0x3b); /* + MCKO bit */
198 ak4642_write(codec, 0x01, 0x7b); /* + MCKO bit */
199 } else {
200 /*
201 * start stereo input
202 *
203 * PLL Master Mode
204 * Audio I/F Format:MSB justified (ADC & DAC)
205 * Sampling Frequency:44.1kHz
206 * Pre MIC AMP:+20dB
207 * MIC Power On
208 * ALC setting:Refer to Table 35
209 * ALC bit=“1”
210 *
211 * This operation came from example code of
212 * "ASAHI KASEI AK4642" (japanese) manual p94.
213 */
214 ak4642_write(codec, 0x05, 0x27);
215 ak4642_write(codec, 0x02, 0x05);
216 ak4642_write(codec, 0x06, 0x3c);
217 ak4642_write(codec, 0x08, 0xe1);
218 ak4642_write(codec, 0x0b, 0x00);
219 ak4642_write(codec, 0x07, 0x21);
220 ak4642_write(codec, 0x00, 0x41);
221 ak4642_write(codec, 0x10, 0x01);
222 }
223
224 return 0;
225}
226
227static void ak4642_dai_shutdown(struct snd_pcm_substream *substream,
228 struct snd_soc_dai *dai)
229{
230 int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
231 struct snd_soc_codec *codec = dai->codec;
232
233 if (is_play) {
234 /* stop headphone output */
235 ak4642_write(codec, 0x01, 0x3b);
236 ak4642_write(codec, 0x01, 0x0b);
237 ak4642_write(codec, 0x00, 0x40);
238 ak4642_write(codec, 0x0e, 0x11);
239 ak4642_write(codec, 0x0f, 0x08);
240 } else {
241 /* stop stereo input */
242 ak4642_write(codec, 0x00, 0x40);
243 ak4642_write(codec, 0x10, 0x00);
244 ak4642_write(codec, 0x07, 0x01);
245 }
246}
247
248static int ak4642_dai_set_sysclk(struct snd_soc_dai *codec_dai,
249 int clk_id, unsigned int freq, int dir)
250{
251 struct snd_soc_codec *codec = codec_dai->codec;
252 struct ak4642_priv *ak4642 = codec->private_data;
253
254 ak4642->sysclk = freq;
255 return 0;
256}
257
258static struct snd_soc_dai_ops ak4642_dai_ops = {
259 .startup = ak4642_dai_startup,
260 .shutdown = ak4642_dai_shutdown,
261 .set_sysclk = ak4642_dai_set_sysclk,
262};
263
264struct snd_soc_dai ak4642_dai = {
265 .name = "AK4642",
266 .playback = {
267 .stream_name = "Playback",
268 .channels_min = 1,
269 .channels_max = 2,
270 .rates = SNDRV_PCM_RATE_8000_48000,
271 .formats = SNDRV_PCM_FMTBIT_S16_LE },
272 .capture = {
273 .stream_name = "Capture",
274 .channels_min = 1,
275 .channels_max = 2,
276 .rates = SNDRV_PCM_RATE_8000_48000,
277 .formats = SNDRV_PCM_FMTBIT_S16_LE },
278 .ops = &ak4642_dai_ops,
279};
280EXPORT_SYMBOL_GPL(ak4642_dai);
281
282static int ak4642_resume(struct platform_device *pdev)
283{
284 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
285 struct snd_soc_codec *codec = socdev->card->codec;
286
287 ak4642_sync(codec);
288 return 0;
289}
290
291/*
292 * initialise the AK4642 driver
293 * register the mixer and dsp interfaces with the kernel
294 */
295static int ak4642_init(struct ak4642_priv *ak4642)
296{
297 struct snd_soc_codec *codec = &ak4642->codec;
298 int ret = 0;
299
300 if (ak4642_codec) {
301 dev_err(codec->dev, "Another ak4642 is registered\n");
302 return -EINVAL;
303 }
304
305 mutex_init(&codec->mutex);
306 INIT_LIST_HEAD(&codec->dapm_widgets);
307 INIT_LIST_HEAD(&codec->dapm_paths);
308
309 codec->private_data = ak4642;
310 codec->name = "AK4642";
311 codec->owner = THIS_MODULE;
312 codec->read = ak4642_read_reg_cache;
313 codec->write = ak4642_write;
314 codec->dai = &ak4642_dai;
315 codec->num_dai = 1;
316 codec->hw_write = (hw_write_t)i2c_master_send;
317 codec->reg_cache_size = ARRAY_SIZE(ak4642_reg);
318 codec->reg_cache = kmemdup(ak4642_reg,
319 sizeof(ak4642_reg), GFP_KERNEL);
320
321 if (!codec->reg_cache)
322 return -ENOMEM;
323
324 ak4642_dai.dev = codec->dev;
325 ak4642_codec = codec;
326
327 ret = snd_soc_register_codec(codec);
328 if (ret) {
329 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
330 goto reg_cache_err;
331 }
332
333 ret = snd_soc_register_dai(&ak4642_dai);
334 if (ret) {
335 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
336 snd_soc_unregister_codec(codec);
337 goto reg_cache_err;
338 }
339
340 /*
341 * clock setting
342 *
343 * Audio I/F Format: MSB justified (ADC & DAC)
344 * BICK frequency at Master Mode: 64fs
345 * Input Master Clock Select at PLL Mode: 11.2896MHz
346 * MCKO: Enable
347 * Sampling Frequency: 44.1kHz
348 *
349 * This operation came from example code of
350 * "ASAHI KASEI AK4642" (japanese) manual p89.
351 *
352 * please fix-me
353 */
354 ak4642_write(codec, 0x01, 0x08);
355 ak4642_write(codec, 0x04, 0x4a);
356 ak4642_write(codec, 0x05, 0x27);
357 ak4642_write(codec, 0x00, 0x40);
358 ak4642_write(codec, 0x01, 0x0b);
359
360 return ret;
361
362reg_cache_err:
363 kfree(codec->reg_cache);
364 codec->reg_cache = NULL;
365
366 return ret;
367}
368
369#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
370static int ak4642_i2c_probe(struct i2c_client *i2c,
371 const struct i2c_device_id *id)
372{
373 struct ak4642_priv *ak4642;
374 struct snd_soc_codec *codec;
375 int ret;
376
377 ak4642 = kzalloc(sizeof(struct ak4642_priv), GFP_KERNEL);
378 if (!ak4642)
379 return -ENOMEM;
380
381 codec = &ak4642->codec;
382 codec->dev = &i2c->dev;
383
384 i2c_set_clientdata(i2c, ak4642);
385 codec->control_data = i2c;
386
387 ret = ak4642_init(ak4642);
388 if (ret < 0)
389 printk(KERN_ERR "failed to initialise AK4642\n");
390
391 return ret;
392}
393
394static int ak4642_i2c_remove(struct i2c_client *client)
395{
396 struct ak4642_priv *ak4642 = i2c_get_clientdata(client);
397
398 snd_soc_unregister_dai(&ak4642_dai);
399 snd_soc_unregister_codec(&ak4642->codec);
400 kfree(ak4642->codec.reg_cache);
401 kfree(ak4642);
402 ak4642_codec = NULL;
403
404 return 0;
405}
406
407static const struct i2c_device_id ak4642_i2c_id[] = {
408 { "ak4642", 0 },
409 { "ak4643", 0 },
410 { }
411};
412MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id);
413
414static struct i2c_driver ak4642_i2c_driver = {
415 .driver = {
416 .name = "AK4642 I2C Codec",
417 .owner = THIS_MODULE,
418 },
419 .probe = ak4642_i2c_probe,
420 .remove = ak4642_i2c_remove,
421 .id_table = ak4642_i2c_id,
422};
423
424#endif
425
426static int ak4642_probe(struct platform_device *pdev)
427{
428 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
429 int ret;
430
431 if (!ak4642_codec) {
432 dev_err(&pdev->dev, "Codec device not registered\n");
433 return -ENODEV;
434 }
435
436 socdev->card->codec = ak4642_codec;
437
438 /* register pcms */
439 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
440 if (ret < 0) {
441 printk(KERN_ERR "ak4642: failed to create pcms\n");
442 goto pcm_err;
443 }
444
445 ret = snd_soc_init_card(socdev);
446 if (ret < 0) {
447 printk(KERN_ERR "ak4642: failed to register card\n");
448 goto card_err;
449 }
450
451 dev_info(&pdev->dev, "AK4642 Audio Codec %s", AK4642_VERSION);
452 return ret;
453
454card_err:
455 snd_soc_free_pcms(socdev);
456 snd_soc_dapm_free(socdev);
457pcm_err:
458 return ret;
459
460}
461
462/* power down chip */
463static int ak4642_remove(struct platform_device *pdev)
464{
465 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
466
467 snd_soc_free_pcms(socdev);
468 snd_soc_dapm_free(socdev);
469
470 return 0;
471}
472
473struct snd_soc_codec_device soc_codec_dev_ak4642 = {
474 .probe = ak4642_probe,
475 .remove = ak4642_remove,
476 .resume = ak4642_resume,
477};
478EXPORT_SYMBOL_GPL(soc_codec_dev_ak4642);
479
480static int __init ak4642_modinit(void)
481{
482 int ret;
483#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
484 ret = i2c_add_driver(&ak4642_i2c_driver);
485#endif
486 return ret;
487
488}
489module_init(ak4642_modinit);
490
491static void __exit ak4642_exit(void)
492{
493#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
494 i2c_del_driver(&ak4642_i2c_driver);
495#endif
496
497}
498module_exit(ak4642_exit);
499
500MODULE_DESCRIPTION("Soc AK4642 driver");
501MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>");
502MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ak4642.h b/sound/soc/codecs/ak4642.h
new file mode 100644
index 000000000000..e476833d314e
--- /dev/null
+++ b/sound/soc/codecs/ak4642.h
@@ -0,0 +1,20 @@
1/*
2 * ak4642.h -- AK4642 Soc Audio driver
3 *
4 * Copyright (C) 2009 Renesas Solutions Corp.
5 * Kuninori Morimoto <morimoto.kuninori@renesas.com>
6 *
7 * Based on ak4535.c
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 version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#ifndef _AK4642_H
15#define _AK4642_H
16
17extern struct snd_soc_dai ak4642_dai;
18extern struct snd_soc_codec_device soc_codec_dev_ak4642;
19
20#endif
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c
new file mode 100644
index 000000000000..b61214d1c5de
--- /dev/null
+++ b/sound/soc/codecs/ak4671.c
@@ -0,0 +1,825 @@
1/*
2 * ak4671.c -- audio driver for AK4671
3 *
4 * Copyright (C) 2009 Samsung Electronics Co.Ltd
5 * Author: Joonyoung Shim <jy0922.shim@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/init.h>
16#include <linux/i2c.h>
17#include <linux/delay.h>
18#include <sound/soc.h>
19#include <sound/soc-dapm.h>
20#include <sound/initval.h>
21#include <sound/tlv.h>
22
23#include "ak4671.h"
24
25static struct snd_soc_codec *ak4671_codec;
26
27/* codec private data */
28struct ak4671_priv {
29 struct snd_soc_codec codec;
30 u8 reg_cache[AK4671_CACHEREGNUM];
31};
32
33/* ak4671 register cache & default register settings */
34static const u8 ak4671_reg[AK4671_CACHEREGNUM] = {
35 0x00, /* AK4671_AD_DA_POWER_MANAGEMENT (0x00) */
36 0xf6, /* AK4671_PLL_MODE_SELECT0 (0x01) */
37 0x00, /* AK4671_PLL_MODE_SELECT1 (0x02) */
38 0x02, /* AK4671_FORMAT_SELECT (0x03) */
39 0x00, /* AK4671_MIC_SIGNAL_SELECT (0x04) */
40 0x55, /* AK4671_MIC_AMP_GAIN (0x05) */
41 0x00, /* AK4671_MIXING_POWER_MANAGEMENT0 (0x06) */
42 0x00, /* AK4671_MIXING_POWER_MANAGEMENT1 (0x07) */
43 0xb5, /* AK4671_OUTPUT_VOLUME_CONTROL (0x08) */
44 0x00, /* AK4671_LOUT1_SIGNAL_SELECT (0x09) */
45 0x00, /* AK4671_ROUT1_SIGNAL_SELECT (0x0a) */
46 0x00, /* AK4671_LOUT2_SIGNAL_SELECT (0x0b) */
47 0x00, /* AK4671_ROUT2_SIGNAL_SELECT (0x0c) */
48 0x00, /* AK4671_LOUT3_SIGNAL_SELECT (0x0d) */
49 0x00, /* AK4671_ROUT3_SIGNAL_SELECT (0x0e) */
50 0x00, /* AK4671_LOUT1_POWER_MANAGERMENT (0x0f) */
51 0x00, /* AK4671_LOUT2_POWER_MANAGERMENT (0x10) */
52 0x80, /* AK4671_LOUT3_POWER_MANAGERMENT (0x11) */
53 0x91, /* AK4671_LCH_INPUT_VOLUME_CONTROL (0x12) */
54 0x91, /* AK4671_RCH_INPUT_VOLUME_CONTROL (0x13) */
55 0xe1, /* AK4671_ALC_REFERENCE_SELECT (0x14) */
56 0x00, /* AK4671_DIGITAL_MIXING_CONTROL (0x15) */
57 0x00, /* AK4671_ALC_TIMER_SELECT (0x16) */
58 0x00, /* AK4671_ALC_MODE_CONTROL (0x17) */
59 0x02, /* AK4671_MODE_CONTROL1 (0x18) */
60 0x01, /* AK4671_MODE_CONTROL2 (0x19) */
61 0x18, /* AK4671_LCH_OUTPUT_VOLUME_CONTROL (0x1a) */
62 0x18, /* AK4671_RCH_OUTPUT_VOLUME_CONTROL (0x1b) */
63 0x00, /* AK4671_SIDETONE_A_CONTROL (0x1c) */
64 0x02, /* AK4671_DIGITAL_FILTER_SELECT (0x1d) */
65 0x00, /* AK4671_FIL3_COEFFICIENT0 (0x1e) */
66 0x00, /* AK4671_FIL3_COEFFICIENT1 (0x1f) */
67 0x00, /* AK4671_FIL3_COEFFICIENT2 (0x20) */
68 0x00, /* AK4671_FIL3_COEFFICIENT3 (0x21) */
69 0x00, /* AK4671_EQ_COEFFICIENT0 (0x22) */
70 0x00, /* AK4671_EQ_COEFFICIENT1 (0x23) */
71 0x00, /* AK4671_EQ_COEFFICIENT2 (0x24) */
72 0x00, /* AK4671_EQ_COEFFICIENT3 (0x25) */
73 0x00, /* AK4671_EQ_COEFFICIENT4 (0x26) */
74 0x00, /* AK4671_EQ_COEFFICIENT5 (0x27) */
75 0xa9, /* AK4671_FIL1_COEFFICIENT0 (0x28) */
76 0x1f, /* AK4671_FIL1_COEFFICIENT1 (0x29) */
77 0xad, /* AK4671_FIL1_COEFFICIENT2 (0x2a) */
78 0x20, /* AK4671_FIL1_COEFFICIENT3 (0x2b) */
79 0x00, /* AK4671_FIL2_COEFFICIENT0 (0x2c) */
80 0x00, /* AK4671_FIL2_COEFFICIENT1 (0x2d) */
81 0x00, /* AK4671_FIL2_COEFFICIENT2 (0x2e) */
82 0x00, /* AK4671_FIL2_COEFFICIENT3 (0x2f) */
83 0x00, /* AK4671_DIGITAL_FILTER_SELECT2 (0x30) */
84 0x00, /* this register not used */
85 0x00, /* AK4671_E1_COEFFICIENT0 (0x32) */
86 0x00, /* AK4671_E1_COEFFICIENT1 (0x33) */
87 0x00, /* AK4671_E1_COEFFICIENT2 (0x34) */
88 0x00, /* AK4671_E1_COEFFICIENT3 (0x35) */
89 0x00, /* AK4671_E1_COEFFICIENT4 (0x36) */
90 0x00, /* AK4671_E1_COEFFICIENT5 (0x37) */
91 0x00, /* AK4671_E2_COEFFICIENT0 (0x38) */
92 0x00, /* AK4671_E2_COEFFICIENT1 (0x39) */
93 0x00, /* AK4671_E2_COEFFICIENT2 (0x3a) */
94 0x00, /* AK4671_E2_COEFFICIENT3 (0x3b) */
95 0x00, /* AK4671_E2_COEFFICIENT4 (0x3c) */
96 0x00, /* AK4671_E2_COEFFICIENT5 (0x3d) */
97 0x00, /* AK4671_E3_COEFFICIENT0 (0x3e) */
98 0x00, /* AK4671_E3_COEFFICIENT1 (0x3f) */
99 0x00, /* AK4671_E3_COEFFICIENT2 (0x40) */
100 0x00, /* AK4671_E3_COEFFICIENT3 (0x41) */
101 0x00, /* AK4671_E3_COEFFICIENT4 (0x42) */
102 0x00, /* AK4671_E3_COEFFICIENT5 (0x43) */
103 0x00, /* AK4671_E4_COEFFICIENT0 (0x44) */
104 0x00, /* AK4671_E4_COEFFICIENT1 (0x45) */
105 0x00, /* AK4671_E4_COEFFICIENT2 (0x46) */
106 0x00, /* AK4671_E4_COEFFICIENT3 (0x47) */
107 0x00, /* AK4671_E4_COEFFICIENT4 (0x48) */
108 0x00, /* AK4671_E4_COEFFICIENT5 (0x49) */
109 0x00, /* AK4671_E5_COEFFICIENT0 (0x4a) */
110 0x00, /* AK4671_E5_COEFFICIENT1 (0x4b) */
111 0x00, /* AK4671_E5_COEFFICIENT2 (0x4c) */
112 0x00, /* AK4671_E5_COEFFICIENT3 (0x4d) */
113 0x00, /* AK4671_E5_COEFFICIENT4 (0x4e) */
114 0x00, /* AK4671_E5_COEFFICIENT5 (0x4f) */
115 0x88, /* AK4671_EQ_CONTROL_250HZ_100HZ (0x50) */
116 0x88, /* AK4671_EQ_CONTROL_3500HZ_1KHZ (0x51) */
117 0x08, /* AK4671_EQ_CONTRO_10KHZ (0x52) */
118 0x00, /* AK4671_PCM_IF_CONTROL0 (0x53) */
119 0x00, /* AK4671_PCM_IF_CONTROL1 (0x54) */
120 0x00, /* AK4671_PCM_IF_CONTROL2 (0x55) */
121 0x18, /* AK4671_DIGITAL_VOLUME_B_CONTROL (0x56) */
122 0x18, /* AK4671_DIGITAL_VOLUME_C_CONTROL (0x57) */
123 0x00, /* AK4671_SIDETONE_VOLUME_CONTROL (0x58) */
124 0x00, /* AK4671_DIGITAL_MIXING_CONTROL2 (0x59) */
125 0x00, /* AK4671_SAR_ADC_CONTROL (0x5a) */
126};
127
128/*
129 * LOUT1/ROUT1 output volume control:
130 * from -24 to 6 dB in 6 dB steps (mute instead of -30 dB)
131 */
132static DECLARE_TLV_DB_SCALE(out1_tlv, -3000, 600, 1);
133
134/*
135 * LOUT2/ROUT2 output volume control:
136 * from -33 to 6 dB in 3 dB steps (mute instead of -33 dB)
137 */
138static DECLARE_TLV_DB_SCALE(out2_tlv, -3300, 300, 1);
139
140/*
141 * LOUT3/ROUT3 output volume control:
142 * from -6 to 3 dB in 3 dB steps
143 */
144static DECLARE_TLV_DB_SCALE(out3_tlv, -600, 300, 0);
145
146/*
147 * Mic amp gain control:
148 * from -15 to 30 dB in 3 dB steps
149 * REVISIT: The actual min value(0x01) is -12 dB and the reg value 0x00 is not
150 * available
151 */
152static DECLARE_TLV_DB_SCALE(mic_amp_tlv, -1500, 300, 0);
153
154static const struct snd_kcontrol_new ak4671_snd_controls[] = {
155 /* Common playback gain controls */
156 SOC_SINGLE_TLV("Line Output1 Playback Volume",
157 AK4671_OUTPUT_VOLUME_CONTROL, 0, 0x6, 0, out1_tlv),
158 SOC_SINGLE_TLV("Headphone Output2 Playback Volume",
159 AK4671_OUTPUT_VOLUME_CONTROL, 4, 0xd, 0, out2_tlv),
160 SOC_SINGLE_TLV("Line Output3 Playback Volume",
161 AK4671_LOUT3_POWER_MANAGERMENT, 6, 0x3, 0, out3_tlv),
162
163 /* Common capture gain controls */
164 SOC_DOUBLE_TLV("Mic Amp Capture Volume",
165 AK4671_MIC_AMP_GAIN, 0, 4, 0xf, 0, mic_amp_tlv),
166};
167
168/* event handlers */
169static int ak4671_out2_event(struct snd_soc_dapm_widget *w,
170 struct snd_kcontrol *kcontrol, int event)
171{
172 struct snd_soc_codec *codec = w->codec;
173 u8 reg;
174
175 switch (event) {
176 case SND_SOC_DAPM_POST_PMU:
177 reg = snd_soc_read(codec, AK4671_LOUT2_POWER_MANAGERMENT);
178 reg |= AK4671_MUTEN;
179 snd_soc_write(codec, AK4671_LOUT2_POWER_MANAGERMENT, reg);
180 break;
181 case SND_SOC_DAPM_PRE_PMD:
182 reg = snd_soc_read(codec, AK4671_LOUT2_POWER_MANAGERMENT);
183 reg &= ~AK4671_MUTEN;
184 snd_soc_write(codec, AK4671_LOUT2_POWER_MANAGERMENT, reg);
185 break;
186 }
187
188 return 0;
189}
190
191/* Output Mixers */
192static const struct snd_kcontrol_new ak4671_lout1_mixer_controls[] = {
193 SOC_DAPM_SINGLE("DACL", AK4671_LOUT1_SIGNAL_SELECT, 0, 1, 0),
194 SOC_DAPM_SINGLE("LINL1", AK4671_LOUT1_SIGNAL_SELECT, 1, 1, 0),
195 SOC_DAPM_SINGLE("LINL2", AK4671_LOUT1_SIGNAL_SELECT, 2, 1, 0),
196 SOC_DAPM_SINGLE("LINL3", AK4671_LOUT1_SIGNAL_SELECT, 3, 1, 0),
197 SOC_DAPM_SINGLE("LINL4", AK4671_LOUT1_SIGNAL_SELECT, 4, 1, 0),
198 SOC_DAPM_SINGLE("LOOPL", AK4671_LOUT1_SIGNAL_SELECT, 5, 1, 0),
199};
200
201static const struct snd_kcontrol_new ak4671_rout1_mixer_controls[] = {
202 SOC_DAPM_SINGLE("DACR", AK4671_ROUT1_SIGNAL_SELECT, 0, 1, 0),
203 SOC_DAPM_SINGLE("RINR1", AK4671_ROUT1_SIGNAL_SELECT, 1, 1, 0),
204 SOC_DAPM_SINGLE("RINR2", AK4671_ROUT1_SIGNAL_SELECT, 2, 1, 0),
205 SOC_DAPM_SINGLE("RINR3", AK4671_ROUT1_SIGNAL_SELECT, 3, 1, 0),
206 SOC_DAPM_SINGLE("RINR4", AK4671_ROUT1_SIGNAL_SELECT, 4, 1, 0),
207 SOC_DAPM_SINGLE("LOOPR", AK4671_ROUT1_SIGNAL_SELECT, 5, 1, 0),
208};
209
210static const struct snd_kcontrol_new ak4671_lout2_mixer_controls[] = {
211 SOC_DAPM_SINGLE("DACHL", AK4671_LOUT2_SIGNAL_SELECT, 0, 1, 0),
212 SOC_DAPM_SINGLE("LINH1", AK4671_LOUT2_SIGNAL_SELECT, 1, 1, 0),
213 SOC_DAPM_SINGLE("LINH2", AK4671_LOUT2_SIGNAL_SELECT, 2, 1, 0),
214 SOC_DAPM_SINGLE("LINH3", AK4671_LOUT2_SIGNAL_SELECT, 3, 1, 0),
215 SOC_DAPM_SINGLE("LINH4", AK4671_LOUT2_SIGNAL_SELECT, 4, 1, 0),
216 SOC_DAPM_SINGLE("LOOPHL", AK4671_LOUT2_SIGNAL_SELECT, 5, 1, 0),
217};
218
219static const struct snd_kcontrol_new ak4671_rout2_mixer_controls[] = {
220 SOC_DAPM_SINGLE("DACHR", AK4671_ROUT2_SIGNAL_SELECT, 0, 1, 0),
221 SOC_DAPM_SINGLE("RINH1", AK4671_ROUT2_SIGNAL_SELECT, 1, 1, 0),
222 SOC_DAPM_SINGLE("RINH2", AK4671_ROUT2_SIGNAL_SELECT, 2, 1, 0),
223 SOC_DAPM_SINGLE("RINH3", AK4671_ROUT2_SIGNAL_SELECT, 3, 1, 0),
224 SOC_DAPM_SINGLE("RINH4", AK4671_ROUT2_SIGNAL_SELECT, 4, 1, 0),
225 SOC_DAPM_SINGLE("LOOPHR", AK4671_ROUT2_SIGNAL_SELECT, 5, 1, 0),
226};
227
228static const struct snd_kcontrol_new ak4671_lout3_mixer_controls[] = {
229 SOC_DAPM_SINGLE("DACSL", AK4671_LOUT3_SIGNAL_SELECT, 0, 1, 0),
230 SOC_DAPM_SINGLE("LINS1", AK4671_LOUT3_SIGNAL_SELECT, 1, 1, 0),
231 SOC_DAPM_SINGLE("LINS2", AK4671_LOUT3_SIGNAL_SELECT, 2, 1, 0),
232 SOC_DAPM_SINGLE("LINS3", AK4671_LOUT3_SIGNAL_SELECT, 3, 1, 0),
233 SOC_DAPM_SINGLE("LINS4", AK4671_LOUT3_SIGNAL_SELECT, 4, 1, 0),
234 SOC_DAPM_SINGLE("LOOPSL", AK4671_LOUT3_SIGNAL_SELECT, 5, 1, 0),
235};
236
237static const struct snd_kcontrol_new ak4671_rout3_mixer_controls[] = {
238 SOC_DAPM_SINGLE("DACSR", AK4671_ROUT3_SIGNAL_SELECT, 0, 1, 0),
239 SOC_DAPM_SINGLE("RINS1", AK4671_ROUT3_SIGNAL_SELECT, 1, 1, 0),
240 SOC_DAPM_SINGLE("RINS2", AK4671_ROUT3_SIGNAL_SELECT, 2, 1, 0),
241 SOC_DAPM_SINGLE("RINS3", AK4671_ROUT3_SIGNAL_SELECT, 3, 1, 0),
242 SOC_DAPM_SINGLE("RINS4", AK4671_ROUT3_SIGNAL_SELECT, 4, 1, 0),
243 SOC_DAPM_SINGLE("LOOPSR", AK4671_ROUT3_SIGNAL_SELECT, 5, 1, 0),
244};
245
246/* Input MUXs */
247static const char *ak4671_lin_mux_texts[] =
248 {"LIN1", "LIN2", "LIN3", "LIN4"};
249static const struct soc_enum ak4671_lin_mux_enum =
250 SOC_ENUM_SINGLE(AK4671_MIC_SIGNAL_SELECT, 0,
251 ARRAY_SIZE(ak4671_lin_mux_texts),
252 ak4671_lin_mux_texts);
253static const struct snd_kcontrol_new ak4671_lin_mux_control =
254 SOC_DAPM_ENUM("Route", ak4671_lin_mux_enum);
255
256static const char *ak4671_rin_mux_texts[] =
257 {"RIN1", "RIN2", "RIN3", "RIN4"};
258static const struct soc_enum ak4671_rin_mux_enum =
259 SOC_ENUM_SINGLE(AK4671_MIC_SIGNAL_SELECT, 2,
260 ARRAY_SIZE(ak4671_rin_mux_texts),
261 ak4671_rin_mux_texts);
262static const struct snd_kcontrol_new ak4671_rin_mux_control =
263 SOC_DAPM_ENUM("Route", ak4671_rin_mux_enum);
264
265static const struct snd_soc_dapm_widget ak4671_dapm_widgets[] = {
266 /* Inputs */
267 SND_SOC_DAPM_INPUT("LIN1"),
268 SND_SOC_DAPM_INPUT("RIN1"),
269 SND_SOC_DAPM_INPUT("LIN2"),
270 SND_SOC_DAPM_INPUT("RIN2"),
271 SND_SOC_DAPM_INPUT("LIN3"),
272 SND_SOC_DAPM_INPUT("RIN3"),
273 SND_SOC_DAPM_INPUT("LIN4"),
274 SND_SOC_DAPM_INPUT("RIN4"),
275
276 /* Outputs */
277 SND_SOC_DAPM_OUTPUT("LOUT1"),
278 SND_SOC_DAPM_OUTPUT("ROUT1"),
279 SND_SOC_DAPM_OUTPUT("LOUT2"),
280 SND_SOC_DAPM_OUTPUT("ROUT2"),
281 SND_SOC_DAPM_OUTPUT("LOUT3"),
282 SND_SOC_DAPM_OUTPUT("ROUT3"),
283
284 /* DAC */
285 SND_SOC_DAPM_DAC("DAC Left", "Left HiFi Playback",
286 AK4671_AD_DA_POWER_MANAGEMENT, 6, 0),
287 SND_SOC_DAPM_DAC("DAC Right", "Right HiFi Playback",
288 AK4671_AD_DA_POWER_MANAGEMENT, 7, 0),
289
290 /* ADC */
291 SND_SOC_DAPM_ADC("ADC Left", "Left HiFi Capture",
292 AK4671_AD_DA_POWER_MANAGEMENT, 4, 0),
293 SND_SOC_DAPM_ADC("ADC Right", "Right HiFi Capture",
294 AK4671_AD_DA_POWER_MANAGEMENT, 5, 0),
295
296 /* PGA */
297 SND_SOC_DAPM_PGA("LOUT2 Mix Amp",
298 AK4671_LOUT2_POWER_MANAGERMENT, 5, 0, NULL, 0),
299 SND_SOC_DAPM_PGA("ROUT2 Mix Amp",
300 AK4671_LOUT2_POWER_MANAGERMENT, 6, 0, NULL, 0),
301
302 SND_SOC_DAPM_PGA("LIN1 Mixing Circuit",
303 AK4671_MIXING_POWER_MANAGEMENT1, 0, 0, NULL, 0),
304 SND_SOC_DAPM_PGA("RIN1 Mixing Circuit",
305 AK4671_MIXING_POWER_MANAGEMENT1, 1, 0, NULL, 0),
306 SND_SOC_DAPM_PGA("LIN2 Mixing Circuit",
307 AK4671_MIXING_POWER_MANAGEMENT1, 2, 0, NULL, 0),
308 SND_SOC_DAPM_PGA("RIN2 Mixing Circuit",
309 AK4671_MIXING_POWER_MANAGEMENT1, 3, 0, NULL, 0),
310 SND_SOC_DAPM_PGA("LIN3 Mixing Circuit",
311 AK4671_MIXING_POWER_MANAGEMENT1, 4, 0, NULL, 0),
312 SND_SOC_DAPM_PGA("RIN3 Mixing Circuit",
313 AK4671_MIXING_POWER_MANAGEMENT1, 5, 0, NULL, 0),
314 SND_SOC_DAPM_PGA("LIN4 Mixing Circuit",
315 AK4671_MIXING_POWER_MANAGEMENT1, 6, 0, NULL, 0),
316 SND_SOC_DAPM_PGA("RIN4 Mixing Circuit",
317 AK4671_MIXING_POWER_MANAGEMENT1, 7, 0, NULL, 0),
318
319 /* Output Mixers */
320 SND_SOC_DAPM_MIXER("LOUT1 Mixer", AK4671_LOUT1_POWER_MANAGERMENT, 0, 0,
321 &ak4671_lout1_mixer_controls[0],
322 ARRAY_SIZE(ak4671_lout1_mixer_controls)),
323 SND_SOC_DAPM_MIXER("ROUT1 Mixer", AK4671_LOUT1_POWER_MANAGERMENT, 1, 0,
324 &ak4671_rout1_mixer_controls[0],
325 ARRAY_SIZE(ak4671_rout1_mixer_controls)),
326 SND_SOC_DAPM_MIXER_E("LOUT2 Mixer", AK4671_LOUT2_POWER_MANAGERMENT,
327 0, 0, &ak4671_lout2_mixer_controls[0],
328 ARRAY_SIZE(ak4671_lout2_mixer_controls),
329 ak4671_out2_event,
330 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_PRE_PMD),
331 SND_SOC_DAPM_MIXER_E("ROUT2 Mixer", AK4671_LOUT2_POWER_MANAGERMENT,
332 1, 0, &ak4671_rout2_mixer_controls[0],
333 ARRAY_SIZE(ak4671_rout2_mixer_controls),
334 ak4671_out2_event,
335 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_PRE_PMD),
336 SND_SOC_DAPM_MIXER("LOUT3 Mixer", AK4671_LOUT3_POWER_MANAGERMENT, 0, 0,
337 &ak4671_lout3_mixer_controls[0],
338 ARRAY_SIZE(ak4671_lout3_mixer_controls)),
339 SND_SOC_DAPM_MIXER("ROUT3 Mixer", AK4671_LOUT3_POWER_MANAGERMENT, 1, 0,
340 &ak4671_rout3_mixer_controls[0],
341 ARRAY_SIZE(ak4671_rout3_mixer_controls)),
342
343 /* Input MUXs */
344 SND_SOC_DAPM_MUX("LIN MUX", AK4671_AD_DA_POWER_MANAGEMENT, 2, 0,
345 &ak4671_lin_mux_control),
346 SND_SOC_DAPM_MUX("RIN MUX", AK4671_AD_DA_POWER_MANAGEMENT, 3, 0,
347 &ak4671_rin_mux_control),
348
349 /* Mic Power */
350 SND_SOC_DAPM_MICBIAS("Mic Bias", AK4671_AD_DA_POWER_MANAGEMENT, 1, 0),
351
352 /* Supply */
353 SND_SOC_DAPM_SUPPLY("PMPLL", AK4671_PLL_MODE_SELECT1, 0, 0, NULL, 0),
354};
355
356static const struct snd_soc_dapm_route intercon[] = {
357 {"DAC Left", "NULL", "PMPLL"},
358 {"DAC Right", "NULL", "PMPLL"},
359 {"ADC Left", "NULL", "PMPLL"},
360 {"ADC Right", "NULL", "PMPLL"},
361
362 /* Outputs */
363 {"LOUT1", "NULL", "LOUT1 Mixer"},
364 {"ROUT1", "NULL", "ROUT1 Mixer"},
365 {"LOUT2", "NULL", "LOUT2 Mix Amp"},
366 {"ROUT2", "NULL", "ROUT2 Mix Amp"},
367 {"LOUT3", "NULL", "LOUT3 Mixer"},
368 {"ROUT3", "NULL", "ROUT3 Mixer"},
369
370 {"LOUT1 Mixer", "DACL", "DAC Left"},
371 {"ROUT1 Mixer", "DACR", "DAC Right"},
372 {"LOUT2 Mixer", "DACHL", "DAC Left"},
373 {"ROUT2 Mixer", "DACHR", "DAC Right"},
374 {"LOUT2 Mix Amp", "NULL", "LOUT2 Mixer"},
375 {"ROUT2 Mix Amp", "NULL", "ROUT2 Mixer"},
376 {"LOUT3 Mixer", "DACSL", "DAC Left"},
377 {"ROUT3 Mixer", "DACSR", "DAC Right"},
378
379 /* Inputs */
380 {"LIN MUX", "LIN1", "LIN1"},
381 {"LIN MUX", "LIN2", "LIN2"},
382 {"LIN MUX", "LIN3", "LIN3"},
383 {"LIN MUX", "LIN4", "LIN4"},
384
385 {"RIN MUX", "RIN1", "RIN1"},
386 {"RIN MUX", "RIN2", "RIN2"},
387 {"RIN MUX", "RIN3", "RIN3"},
388 {"RIN MUX", "RIN4", "RIN4"},
389
390 {"LIN1", NULL, "Mic Bias"},
391 {"RIN1", NULL, "Mic Bias"},
392 {"LIN2", NULL, "Mic Bias"},
393 {"RIN2", NULL, "Mic Bias"},
394
395 {"ADC Left", "NULL", "LIN MUX"},
396 {"ADC Right", "NULL", "RIN MUX"},
397
398 /* Analog Loops */
399 {"LIN1 Mixing Circuit", "NULL", "LIN1"},
400 {"RIN1 Mixing Circuit", "NULL", "RIN1"},
401 {"LIN2 Mixing Circuit", "NULL", "LIN2"},
402 {"RIN2 Mixing Circuit", "NULL", "RIN2"},
403 {"LIN3 Mixing Circuit", "NULL", "LIN3"},
404 {"RIN3 Mixing Circuit", "NULL", "RIN3"},
405 {"LIN4 Mixing Circuit", "NULL", "LIN4"},
406 {"RIN4 Mixing Circuit", "NULL", "RIN4"},
407
408 {"LOUT1 Mixer", "LINL1", "LIN1 Mixing Circuit"},
409 {"ROUT1 Mixer", "RINR1", "RIN1 Mixing Circuit"},
410 {"LOUT2 Mixer", "LINH1", "LIN1 Mixing Circuit"},
411 {"ROUT2 Mixer", "RINH1", "RIN1 Mixing Circuit"},
412 {"LOUT3 Mixer", "LINS1", "LIN1 Mixing Circuit"},
413 {"ROUT3 Mixer", "RINS1", "RIN1 Mixing Circuit"},
414
415 {"LOUT1 Mixer", "LINL2", "LIN2 Mixing Circuit"},
416 {"ROUT1 Mixer", "RINR2", "RIN2 Mixing Circuit"},
417 {"LOUT2 Mixer", "LINH2", "LIN2 Mixing Circuit"},
418 {"ROUT2 Mixer", "RINH2", "RIN2 Mixing Circuit"},
419 {"LOUT3 Mixer", "LINS2", "LIN2 Mixing Circuit"},
420 {"ROUT3 Mixer", "RINS2", "RIN2 Mixing Circuit"},
421
422 {"LOUT1 Mixer", "LINL3", "LIN3 Mixing Circuit"},
423 {"ROUT1 Mixer", "RINR3", "RIN3 Mixing Circuit"},
424 {"LOUT2 Mixer", "LINH3", "LIN3 Mixing Circuit"},
425 {"ROUT2 Mixer", "RINH3", "RIN3 Mixing Circuit"},
426 {"LOUT3 Mixer", "LINS3", "LIN3 Mixing Circuit"},
427 {"ROUT3 Mixer", "RINS3", "RIN3 Mixing Circuit"},
428
429 {"LOUT1 Mixer", "LINL4", "LIN4 Mixing Circuit"},
430 {"ROUT1 Mixer", "RINR4", "RIN4 Mixing Circuit"},
431 {"LOUT2 Mixer", "LINH4", "LIN4 Mixing Circuit"},
432 {"ROUT2 Mixer", "RINH4", "RIN4 Mixing Circuit"},
433 {"LOUT3 Mixer", "LINS4", "LIN4 Mixing Circuit"},
434 {"ROUT3 Mixer", "RINS4", "RIN4 Mixing Circuit"},
435};
436
437static int ak4671_add_widgets(struct snd_soc_codec *codec)
438{
439 snd_soc_dapm_new_controls(codec, ak4671_dapm_widgets,
440 ARRAY_SIZE(ak4671_dapm_widgets));
441
442 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
443
444 snd_soc_dapm_new_widgets(codec);
445 return 0;
446}
447
448static int ak4671_hw_params(struct snd_pcm_substream *substream,
449 struct snd_pcm_hw_params *params,
450 struct snd_soc_dai *dai)
451{
452 struct snd_soc_codec *codec = dai->codec;
453 u8 fs;
454
455 fs = snd_soc_read(codec, AK4671_PLL_MODE_SELECT0);
456 fs &= ~AK4671_FS;
457
458 switch (params_rate(params)) {
459 case 8000:
460 fs |= AK4671_FS_8KHZ;
461 break;
462 case 12000:
463 fs |= AK4671_FS_12KHZ;
464 break;
465 case 16000:
466 fs |= AK4671_FS_16KHZ;
467 break;
468 case 24000:
469 fs |= AK4671_FS_24KHZ;
470 break;
471 case 11025:
472 fs |= AK4671_FS_11_025KHZ;
473 break;
474 case 22050:
475 fs |= AK4671_FS_22_05KHZ;
476 break;
477 case 32000:
478 fs |= AK4671_FS_32KHZ;
479 break;
480 case 44100:
481 fs |= AK4671_FS_44_1KHZ;
482 break;
483 case 48000:
484 fs |= AK4671_FS_48KHZ;
485 break;
486 default:
487 return -EINVAL;
488 }
489
490 snd_soc_write(codec, AK4671_PLL_MODE_SELECT0, fs);
491
492 return 0;
493}
494
495static int ak4671_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
496 unsigned int freq, int dir)
497{
498 struct snd_soc_codec *codec = dai->codec;
499 u8 pll;
500
501 pll = snd_soc_read(codec, AK4671_PLL_MODE_SELECT0);
502 pll &= ~AK4671_PLL;
503
504 switch (freq) {
505 case 11289600:
506 pll |= AK4671_PLL_11_2896MHZ;
507 break;
508 case 12000000:
509 pll |= AK4671_PLL_12MHZ;
510 break;
511 case 12288000:
512 pll |= AK4671_PLL_12_288MHZ;
513 break;
514 case 13000000:
515 pll |= AK4671_PLL_13MHZ;
516 break;
517 case 13500000:
518 pll |= AK4671_PLL_13_5MHZ;
519 break;
520 case 19200000:
521 pll |= AK4671_PLL_19_2MHZ;
522 break;
523 case 24000000:
524 pll |= AK4671_PLL_24MHZ;
525 break;
526 case 26000000:
527 pll |= AK4671_PLL_26MHZ;
528 break;
529 case 27000000:
530 pll |= AK4671_PLL_27MHZ;
531 break;
532 default:
533 return -EINVAL;
534 }
535
536 snd_soc_write(codec, AK4671_PLL_MODE_SELECT0, pll);
537
538 return 0;
539}
540
541static int ak4671_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
542{
543 struct snd_soc_codec *codec = dai->codec;
544 u8 mode;
545 u8 format;
546
547 /* set master/slave audio interface */
548 mode = snd_soc_read(codec, AK4671_PLL_MODE_SELECT1);
549
550 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
551 case SND_SOC_DAIFMT_CBM_CFM:
552 mode |= AK4671_M_S;
553 break;
554 case SND_SOC_DAIFMT_CBM_CFS:
555 mode &= ~(AK4671_M_S);
556 break;
557 default:
558 return -EINVAL;
559 }
560
561 /* interface format */
562 format = snd_soc_read(codec, AK4671_FORMAT_SELECT);
563 format &= ~AK4671_DIF;
564
565 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
566 case SND_SOC_DAIFMT_I2S:
567 format |= AK4671_DIF_I2S_MODE;
568 break;
569 case SND_SOC_DAIFMT_LEFT_J:
570 format |= AK4671_DIF_MSB_MODE;
571 break;
572 case SND_SOC_DAIFMT_DSP_A:
573 format |= AK4671_DIF_DSP_MODE;
574 format |= AK4671_BCKP;
575 format |= AK4671_MSBS;
576 break;
577 default:
578 return -EINVAL;
579 }
580
581 /* set mode and format */
582 snd_soc_write(codec, AK4671_PLL_MODE_SELECT1, mode);
583 snd_soc_write(codec, AK4671_FORMAT_SELECT, format);
584
585 return 0;
586}
587
588static int ak4671_set_bias_level(struct snd_soc_codec *codec,
589 enum snd_soc_bias_level level)
590{
591 u8 reg;
592
593 switch (level) {
594 case SND_SOC_BIAS_ON:
595 case SND_SOC_BIAS_PREPARE:
596 case SND_SOC_BIAS_STANDBY:
597 reg = snd_soc_read(codec, AK4671_AD_DA_POWER_MANAGEMENT);
598 snd_soc_write(codec, AK4671_AD_DA_POWER_MANAGEMENT,
599 reg | AK4671_PMVCM);
600 break;
601 case SND_SOC_BIAS_OFF:
602 snd_soc_write(codec, AK4671_AD_DA_POWER_MANAGEMENT, 0x00);
603 break;
604 }
605 codec->bias_level = level;
606 return 0;
607}
608
609#define AK4671_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
610 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
611 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
612 SNDRV_PCM_RATE_48000)
613
614#define AK4671_FORMATS SNDRV_PCM_FMTBIT_S16_LE
615
616static struct snd_soc_dai_ops ak4671_dai_ops = {
617 .hw_params = ak4671_hw_params,
618 .set_sysclk = ak4671_set_dai_sysclk,
619 .set_fmt = ak4671_set_dai_fmt,
620};
621
622struct snd_soc_dai ak4671_dai = {
623 .name = "AK4671",
624 .playback = {
625 .stream_name = "Playback",
626 .channels_min = 1,
627 .channels_max = 2,
628 .rates = AK4671_RATES,
629 .formats = AK4671_FORMATS,},
630 .capture = {
631 .stream_name = "Capture",
632 .channels_min = 1,
633 .channels_max = 2,
634 .rates = AK4671_RATES,
635 .formats = AK4671_FORMATS,},
636 .ops = &ak4671_dai_ops,
637};
638EXPORT_SYMBOL_GPL(ak4671_dai);
639
640static int ak4671_probe(struct platform_device *pdev)
641{
642 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
643 struct snd_soc_codec *codec;
644 int ret = 0;
645
646 if (ak4671_codec == NULL) {
647 dev_err(&pdev->dev, "Codec device not registered\n");
648 return -ENODEV;
649 }
650
651 socdev->card->codec = ak4671_codec;
652 codec = ak4671_codec;
653
654 /* register pcms */
655 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
656 if (ret < 0) {
657 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
658 goto pcm_err;
659 }
660
661 snd_soc_add_controls(codec, ak4671_snd_controls,
662 ARRAY_SIZE(ak4671_snd_controls));
663 ak4671_add_widgets(codec);
664
665 ret = snd_soc_init_card(socdev);
666 if (ret < 0) {
667 dev_err(codec->dev, "failed to register card: %d\n", ret);
668 goto card_err;
669 }
670
671 ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
672
673 return ret;
674
675card_err:
676 snd_soc_free_pcms(socdev);
677 snd_soc_dapm_free(socdev);
678pcm_err:
679 return ret;
680}
681
682static int ak4671_remove(struct platform_device *pdev)
683{
684 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
685
686 snd_soc_free_pcms(socdev);
687 snd_soc_dapm_free(socdev);
688
689 return 0;
690}
691
692struct snd_soc_codec_device soc_codec_dev_ak4671 = {
693 .probe = ak4671_probe,
694 .remove = ak4671_remove,
695};
696EXPORT_SYMBOL_GPL(soc_codec_dev_ak4671);
697
698static int ak4671_register(struct ak4671_priv *ak4671,
699 enum snd_soc_control_type control)
700{
701 int ret;
702 struct snd_soc_codec *codec = &ak4671->codec;
703
704 if (ak4671_codec) {
705 dev_err(codec->dev, "Another AK4671 is registered\n");
706 ret = -EINVAL;
707 goto err;
708 }
709
710 mutex_init(&codec->mutex);
711 INIT_LIST_HEAD(&codec->dapm_widgets);
712 INIT_LIST_HEAD(&codec->dapm_paths);
713
714 codec->private_data = ak4671;
715 codec->name = "AK4671";
716 codec->owner = THIS_MODULE;
717 codec->bias_level = SND_SOC_BIAS_OFF;
718 codec->set_bias_level = ak4671_set_bias_level;
719 codec->dai = &ak4671_dai;
720 codec->num_dai = 1;
721 codec->reg_cache_size = AK4671_CACHEREGNUM;
722 codec->reg_cache = &ak4671->reg_cache;
723
724 memcpy(codec->reg_cache, ak4671_reg, sizeof(ak4671_reg));
725
726 ret = snd_soc_codec_set_cache_io(codec, 8, 8, control);
727 if (ret < 0) {
728 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
729 goto err;
730 }
731
732 ak4671_dai.dev = codec->dev;
733 ak4671_codec = codec;
734
735 ret = snd_soc_register_codec(codec);
736 if (ret != 0) {
737 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
738 goto err;
739 }
740
741 ret = snd_soc_register_dai(&ak4671_dai);
742 if (ret != 0) {
743 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
744 goto err_codec;
745 }
746
747 return 0;
748
749err_codec:
750 snd_soc_unregister_codec(codec);
751err:
752 kfree(ak4671);
753 return ret;
754}
755
756static void ak4671_unregister(struct ak4671_priv *ak4671)
757{
758 ak4671_set_bias_level(&ak4671->codec, SND_SOC_BIAS_OFF);
759 snd_soc_unregister_dai(&ak4671_dai);
760 snd_soc_unregister_codec(&ak4671->codec);
761 kfree(ak4671);
762 ak4671_codec = NULL;
763}
764
765static int __devinit ak4671_i2c_probe(struct i2c_client *client,
766 const struct i2c_device_id *id)
767{
768 struct ak4671_priv *ak4671;
769 struct snd_soc_codec *codec;
770
771 ak4671 = kzalloc(sizeof(struct ak4671_priv), GFP_KERNEL);
772 if (ak4671 == NULL)
773 return -ENOMEM;
774
775 codec = &ak4671->codec;
776 codec->hw_write = (hw_write_t)i2c_master_send;
777
778 i2c_set_clientdata(client, ak4671);
779 codec->control_data = client;
780
781 codec->dev = &client->dev;
782
783 return ak4671_register(ak4671, SND_SOC_I2C);
784}
785
786static __devexit int ak4671_i2c_remove(struct i2c_client *client)
787{
788 struct ak4671_priv *ak4671 = i2c_get_clientdata(client);
789
790 ak4671_unregister(ak4671);
791
792 return 0;
793}
794
795static const struct i2c_device_id ak4671_i2c_id[] = {
796 { "ak4671", 0 },
797 { }
798};
799MODULE_DEVICE_TABLE(i2c, ak4671_i2c_id);
800
801static struct i2c_driver ak4671_i2c_driver = {
802 .driver = {
803 .name = "ak4671",
804 .owner = THIS_MODULE,
805 },
806 .probe = ak4671_i2c_probe,
807 .remove = __devexit_p(ak4671_i2c_remove),
808 .id_table = ak4671_i2c_id,
809};
810
811static int __init ak4671_modinit(void)
812{
813 return i2c_add_driver(&ak4671_i2c_driver);
814}
815module_init(ak4671_modinit);
816
817static void __exit ak4671_exit(void)
818{
819 i2c_del_driver(&ak4671_i2c_driver);
820}
821module_exit(ak4671_exit);
822
823MODULE_DESCRIPTION("ASoC AK4671 codec driver");
824MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
825MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ak4671.h b/sound/soc/codecs/ak4671.h
new file mode 100644
index 000000000000..e2fad964e88b
--- /dev/null
+++ b/sound/soc/codecs/ak4671.h
@@ -0,0 +1,156 @@
1/*
2 * ak4671.h -- audio driver for AK4671
3 *
4 * Copyright (C) 2009 Samsung Electronics Co.Ltd
5 * Author: Joonyoung Shim <jy0922.shim@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 */
13
14#ifndef _AK4671_H
15#define _AK4671_H
16
17#define AK4671_AD_DA_POWER_MANAGEMENT 0x00
18#define AK4671_PLL_MODE_SELECT0 0x01
19#define AK4671_PLL_MODE_SELECT1 0x02
20#define AK4671_FORMAT_SELECT 0x03
21#define AK4671_MIC_SIGNAL_SELECT 0x04
22#define AK4671_MIC_AMP_GAIN 0x05
23#define AK4671_MIXING_POWER_MANAGEMENT0 0x06
24#define AK4671_MIXING_POWER_MANAGEMENT1 0x07
25#define AK4671_OUTPUT_VOLUME_CONTROL 0x08
26#define AK4671_LOUT1_SIGNAL_SELECT 0x09
27#define AK4671_ROUT1_SIGNAL_SELECT 0x0a
28#define AK4671_LOUT2_SIGNAL_SELECT 0x0b
29#define AK4671_ROUT2_SIGNAL_SELECT 0x0c
30#define AK4671_LOUT3_SIGNAL_SELECT 0x0d
31#define AK4671_ROUT3_SIGNAL_SELECT 0x0e
32#define AK4671_LOUT1_POWER_MANAGERMENT 0x0f
33#define AK4671_LOUT2_POWER_MANAGERMENT 0x10
34#define AK4671_LOUT3_POWER_MANAGERMENT 0x11
35#define AK4671_LCH_INPUT_VOLUME_CONTROL 0x12
36#define AK4671_RCH_INPUT_VOLUME_CONTROL 0x13
37#define AK4671_ALC_REFERENCE_SELECT 0x14
38#define AK4671_DIGITAL_MIXING_CONTROL 0x15
39#define AK4671_ALC_TIMER_SELECT 0x16
40#define AK4671_ALC_MODE_CONTROL 0x17
41#define AK4671_MODE_CONTROL1 0x18
42#define AK4671_MODE_CONTROL2 0x19
43#define AK4671_LCH_OUTPUT_VOLUME_CONTROL 0x1a
44#define AK4671_RCH_OUTPUT_VOLUME_CONTROL 0x1b
45#define AK4671_SIDETONE_A_CONTROL 0x1c
46#define AK4671_DIGITAL_FILTER_SELECT 0x1d
47#define AK4671_FIL3_COEFFICIENT0 0x1e
48#define AK4671_FIL3_COEFFICIENT1 0x1f
49#define AK4671_FIL3_COEFFICIENT2 0x20
50#define AK4671_FIL3_COEFFICIENT3 0x21
51#define AK4671_EQ_COEFFICIENT0 0x22
52#define AK4671_EQ_COEFFICIENT1 0x23
53#define AK4671_EQ_COEFFICIENT2 0x24
54#define AK4671_EQ_COEFFICIENT3 0x25
55#define AK4671_EQ_COEFFICIENT4 0x26
56#define AK4671_EQ_COEFFICIENT5 0x27
57#define AK4671_FIL1_COEFFICIENT0 0x28
58#define AK4671_FIL1_COEFFICIENT1 0x29
59#define AK4671_FIL1_COEFFICIENT2 0x2a
60#define AK4671_FIL1_COEFFICIENT3 0x2b
61#define AK4671_FIL2_COEFFICIENT0 0x2c
62#define AK4671_FIL2_COEFFICIENT1 0x2d
63#define AK4671_FIL2_COEFFICIENT2 0x2e
64#define AK4671_FIL2_COEFFICIENT3 0x2f
65#define AK4671_DIGITAL_FILTER_SELECT2 0x30
66#define AK4671_E1_COEFFICIENT0 0x32
67#define AK4671_E1_COEFFICIENT1 0x33
68#define AK4671_E1_COEFFICIENT2 0x34
69#define AK4671_E1_COEFFICIENT3 0x35
70#define AK4671_E1_COEFFICIENT4 0x36
71#define AK4671_E1_COEFFICIENT5 0x37
72#define AK4671_E2_COEFFICIENT0 0x38
73#define AK4671_E2_COEFFICIENT1 0x39
74#define AK4671_E2_COEFFICIENT2 0x3a
75#define AK4671_E2_COEFFICIENT3 0x3b
76#define AK4671_E2_COEFFICIENT4 0x3c
77#define AK4671_E2_COEFFICIENT5 0x3d
78#define AK4671_E3_COEFFICIENT0 0x3e
79#define AK4671_E3_COEFFICIENT1 0x3f
80#define AK4671_E3_COEFFICIENT2 0x40
81#define AK4671_E3_COEFFICIENT3 0x41
82#define AK4671_E3_COEFFICIENT4 0x42
83#define AK4671_E3_COEFFICIENT5 0x43
84#define AK4671_E4_COEFFICIENT0 0x44
85#define AK4671_E4_COEFFICIENT1 0x45
86#define AK4671_E4_COEFFICIENT2 0x46
87#define AK4671_E4_COEFFICIENT3 0x47
88#define AK4671_E4_COEFFICIENT4 0x48
89#define AK4671_E4_COEFFICIENT5 0x49
90#define AK4671_E5_COEFFICIENT0 0x4a
91#define AK4671_E5_COEFFICIENT1 0x4b
92#define AK4671_E5_COEFFICIENT2 0x4c
93#define AK4671_E5_COEFFICIENT3 0x4d
94#define AK4671_E5_COEFFICIENT4 0x4e
95#define AK4671_E5_COEFFICIENT5 0x4f
96#define AK4671_EQ_CONTROL_250HZ_100HZ 0x50
97#define AK4671_EQ_CONTROL_3500HZ_1KHZ 0x51
98#define AK4671_EQ_CONTRO_10KHZ 0x52
99#define AK4671_PCM_IF_CONTROL0 0x53
100#define AK4671_PCM_IF_CONTROL1 0x54
101#define AK4671_PCM_IF_CONTROL2 0x55
102#define AK4671_DIGITAL_VOLUME_B_CONTROL 0x56
103#define AK4671_DIGITAL_VOLUME_C_CONTROL 0x57
104#define AK4671_SIDETONE_VOLUME_CONTROL 0x58
105#define AK4671_DIGITAL_MIXING_CONTROL2 0x59
106#define AK4671_SAR_ADC_CONTROL 0x5a
107
108#define AK4671_CACHEREGNUM (AK4671_SAR_ADC_CONTROL + 1)
109
110/* Bitfield Definitions */
111
112/* AK4671_AD_DA_POWER_MANAGEMENT (0x00) Fields */
113#define AK4671_PMVCM 0x01
114
115/* AK4671_PLL_MODE_SELECT0 (0x01) Fields */
116#define AK4671_PLL 0x0f
117#define AK4671_PLL_11_2896MHZ (4 << 0)
118#define AK4671_PLL_12_288MHZ (5 << 0)
119#define AK4671_PLL_12MHZ (6 << 0)
120#define AK4671_PLL_24MHZ (7 << 0)
121#define AK4671_PLL_19_2MHZ (8 << 0)
122#define AK4671_PLL_13_5MHZ (12 << 0)
123#define AK4671_PLL_27MHZ (13 << 0)
124#define AK4671_PLL_13MHZ (14 << 0)
125#define AK4671_PLL_26MHZ (15 << 0)
126#define AK4671_FS 0xf0
127#define AK4671_FS_8KHZ (0 << 4)
128#define AK4671_FS_12KHZ (1 << 4)
129#define AK4671_FS_16KHZ (2 << 4)
130#define AK4671_FS_24KHZ (3 << 4)
131#define AK4671_FS_11_025KHZ (5 << 4)
132#define AK4671_FS_22_05KHZ (7 << 4)
133#define AK4671_FS_32KHZ (10 << 4)
134#define AK4671_FS_48KHZ (11 << 4)
135#define AK4671_FS_44_1KHZ (15 << 4)
136
137/* AK4671_PLL_MODE_SELECT1 (0x02) Fields */
138#define AK4671_PMPLL 0x01
139#define AK4671_M_S 0x02
140
141/* AK4671_FORMAT_SELECT (0x03) Fields */
142#define AK4671_DIF 0x03
143#define AK4671_DIF_DSP_MODE (0 << 0)
144#define AK4671_DIF_MSB_MODE (2 << 0)
145#define AK4671_DIF_I2S_MODE (3 << 0)
146#define AK4671_BCKP 0x04
147#define AK4671_MSBS 0x08
148#define AK4671_SDOD 0x10
149
150/* AK4671_LOUT2_POWER_MANAGEMENT (0x10) Fields */
151#define AK4671_MUTEN 0x04
152
153extern struct snd_soc_dai ak4671_dai;
154extern struct snd_soc_codec_device soc_codec_dev_ak4671;
155
156#endif
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 126b15b18aeb..3395cf945d56 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -53,6 +53,7 @@
53 53
54/* codec private data */ 54/* codec private data */
55struct aic3x_priv { 55struct aic3x_priv {
56 struct snd_soc_codec codec;
56 unsigned int sysclk; 57 unsigned int sysclk;
57 int master; 58 int master;
58}; 59};
@@ -1156,11 +1157,13 @@ static int aic3x_resume(struct platform_device *pdev)
1156 * initialise the AIC3X driver 1157 * initialise the AIC3X driver
1157 * register the mixer and dsp interfaces with the kernel 1158 * register the mixer and dsp interfaces with the kernel
1158 */ 1159 */
1159static int aic3x_init(struct snd_soc_device *socdev) 1160static int aic3x_init(struct snd_soc_codec *codec)
1160{ 1161{
1161 struct snd_soc_codec *codec = socdev->card->codec; 1162 int reg;
1162 struct aic3x_setup_data *setup = socdev->codec_data; 1163
1163 int reg, ret = 0; 1164 mutex_init(&codec->mutex);
1165 INIT_LIST_HEAD(&codec->dapm_widgets);
1166 INIT_LIST_HEAD(&codec->dapm_paths);
1164 1167
1165 codec->name = "tlv320aic3x"; 1168 codec->name = "tlv320aic3x";
1166 codec->owner = THIS_MODULE; 1169 codec->owner = THIS_MODULE;
@@ -1177,13 +1180,6 @@ static int aic3x_init(struct snd_soc_device *socdev)
1177 aic3x_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT); 1180 aic3x_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT);
1178 aic3x_write(codec, AIC3X_RESET, SOFT_RESET); 1181 aic3x_write(codec, AIC3X_RESET, SOFT_RESET);
1179 1182
1180 /* register pcms */
1181 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1182 if (ret < 0) {
1183 printk(KERN_ERR "aic3x: failed to create pcms\n");
1184 goto pcm_err;
1185 }
1186
1187 /* DAC default volume and mute */ 1183 /* DAC default volume and mute */
1188 aic3x_write(codec, LDAC_VOL, DEFAULT_VOL | MUTE_ON); 1184 aic3x_write(codec, LDAC_VOL, DEFAULT_VOL | MUTE_ON);
1189 aic3x_write(codec, RDAC_VOL, DEFAULT_VOL | MUTE_ON); 1185 aic3x_write(codec, RDAC_VOL, DEFAULT_VOL | MUTE_ON);
@@ -1250,30 +1246,51 @@ static int aic3x_init(struct snd_soc_device *socdev)
1250 /* off, with power on */ 1246 /* off, with power on */
1251 aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1247 aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1252 1248
1253 /* setup GPIO functions */ 1249 return 0;
1254 aic3x_write(codec, AIC3X_GPIO1_REG, (setup->gpio_func[0] & 0xf) << 4); 1250}
1255 aic3x_write(codec, AIC3X_GPIO2_REG, (setup->gpio_func[1] & 0xf) << 4);
1256 1251
1257 snd_soc_add_controls(codec, aic3x_snd_controls, 1252static struct snd_soc_codec *aic3x_codec;
1258 ARRAY_SIZE(aic3x_snd_controls)); 1253
1259 aic3x_add_widgets(codec); 1254static int aic3x_register(struct snd_soc_codec *codec)
1260 ret = snd_soc_init_card(socdev); 1255{
1256 int ret;
1257
1258 ret = aic3x_init(codec);
1261 if (ret < 0) { 1259 if (ret < 0) {
1262 printk(KERN_ERR "aic3x: failed to register card\n"); 1260 dev_err(codec->dev, "Failed to initialise device\n");
1263 goto card_err; 1261 return ret;
1264 } 1262 }
1265 1263
1266 return ret; 1264 aic3x_codec = codec;
1267 1265
1268card_err: 1266 ret = snd_soc_register_codec(codec);
1269 snd_soc_free_pcms(socdev); 1267 if (ret) {
1270 snd_soc_dapm_free(socdev); 1268 dev_err(codec->dev, "Failed to register codec\n");
1271pcm_err: 1269 return ret;
1272 kfree(codec->reg_cache); 1270 }
1273 return ret; 1271
1272 ret = snd_soc_register_dai(&aic3x_dai);
1273 if (ret) {
1274 dev_err(codec->dev, "Failed to register dai\n");
1275 snd_soc_unregister_codec(codec);
1276 return ret;
1277 }
1278
1279 return 0;
1274} 1280}
1275 1281
1276static struct snd_soc_device *aic3x_socdev; 1282static int aic3x_unregister(struct aic3x_priv *aic3x)
1283{
1284 aic3x_set_bias_level(&aic3x->codec, SND_SOC_BIAS_OFF);
1285
1286 snd_soc_unregister_dai(&aic3x_dai);
1287 snd_soc_unregister_codec(&aic3x->codec);
1288
1289 kfree(aic3x);
1290 aic3x_codec = NULL;
1291
1292 return 0;
1293}
1277 1294
1278#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1295#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1279/* 1296/*
@@ -1288,28 +1305,36 @@ static struct snd_soc_device *aic3x_socdev;
1288static int aic3x_i2c_probe(struct i2c_client *i2c, 1305static int aic3x_i2c_probe(struct i2c_client *i2c,
1289 const struct i2c_device_id *id) 1306 const struct i2c_device_id *id)
1290{ 1307{
1291 struct snd_soc_device *socdev = aic3x_socdev; 1308 struct snd_soc_codec *codec;
1292 struct snd_soc_codec *codec = socdev->card->codec; 1309 struct aic3x_priv *aic3x;
1293 int ret; 1310
1311 aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL);
1312 if (aic3x == NULL) {
1313 dev_err(&i2c->dev, "failed to create private data\n");
1314 return -ENOMEM;
1315 }
1294 1316
1295 i2c_set_clientdata(i2c, codec); 1317 codec = &aic3x->codec;
1318 codec->dev = &i2c->dev;
1319 codec->private_data = aic3x;
1296 codec->control_data = i2c; 1320 codec->control_data = i2c;
1321 codec->hw_write = (hw_write_t) i2c_master_send;
1297 1322
1298 ret = aic3x_init(socdev); 1323 i2c_set_clientdata(i2c, aic3x);
1299 if (ret < 0) 1324
1300 printk(KERN_ERR "aic3x: failed to initialise AIC3X\n"); 1325 return aic3x_register(codec);
1301 return ret;
1302} 1326}
1303 1327
1304static int aic3x_i2c_remove(struct i2c_client *client) 1328static int aic3x_i2c_remove(struct i2c_client *client)
1305{ 1329{
1306 struct snd_soc_codec *codec = i2c_get_clientdata(client); 1330 struct aic3x_priv *aic3x = i2c_get_clientdata(client);
1307 kfree(codec->reg_cache); 1331
1308 return 0; 1332 return aic3x_unregister(aic3x);
1309} 1333}
1310 1334
1311static const struct i2c_device_id aic3x_i2c_id[] = { 1335static const struct i2c_device_id aic3x_i2c_id[] = {
1312 { "tlv320aic3x", 0 }, 1336 { "tlv320aic3x", 0 },
1337 { "tlv320aic33", 0 },
1313 { } 1338 { }
1314}; 1339};
1315MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); 1340MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
@@ -1320,50 +1345,28 @@ static struct i2c_driver aic3x_i2c_driver = {
1320 .name = "aic3x I2C Codec", 1345 .name = "aic3x I2C Codec",
1321 .owner = THIS_MODULE, 1346 .owner = THIS_MODULE,
1322 }, 1347 },
1323 .probe = aic3x_i2c_probe, 1348 .probe = aic3x_i2c_probe,
1324 .remove = aic3x_i2c_remove, 1349 .remove = aic3x_i2c_remove,
1325 .id_table = aic3x_i2c_id, 1350 .id_table = aic3x_i2c_id,
1326}; 1351};
1327 1352
1328static int aic3x_add_i2c_device(struct platform_device *pdev, 1353static inline void aic3x_i2c_init(void)
1329 const struct aic3x_setup_data *setup)
1330{ 1354{
1331 struct i2c_board_info info;
1332 struct i2c_adapter *adapter;
1333 struct i2c_client *client;
1334 int ret; 1355 int ret;
1335 1356
1336 ret = i2c_add_driver(&aic3x_i2c_driver); 1357 ret = i2c_add_driver(&aic3x_i2c_driver);
1337 if (ret != 0) { 1358 if (ret)
1338 dev_err(&pdev->dev, "can't add i2c driver\n"); 1359 printk(KERN_ERR "%s: error regsitering i2c driver, %d\n",
1339 return ret; 1360 __func__, ret);
1340 } 1361}
1341
1342 memset(&info, 0, sizeof(struct i2c_board_info));
1343 info.addr = setup->i2c_address;
1344 strlcpy(info.type, "tlv320aic3x", I2C_NAME_SIZE);
1345
1346 adapter = i2c_get_adapter(setup->i2c_bus);
1347 if (!adapter) {
1348 dev_err(&pdev->dev, "can't get i2c adapter %d\n",
1349 setup->i2c_bus);
1350 goto err_driver;
1351 }
1352
1353 client = i2c_new_device(adapter, &info);
1354 i2c_put_adapter(adapter);
1355 if (!client) {
1356 dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
1357 (unsigned int)info.addr);
1358 goto err_driver;
1359 }
1360
1361 return 0;
1362 1362
1363err_driver: 1363static inline void aic3x_i2c_exit(void)
1364{
1364 i2c_del_driver(&aic3x_i2c_driver); 1365 i2c_del_driver(&aic3x_i2c_driver);
1365 return -ENODEV;
1366} 1366}
1367#else
1368static inline void aic3x_i2c_init(void) { }
1369static inline void aic3x_i2c_exit(void) { }
1367#endif 1370#endif
1368 1371
1369static int aic3x_probe(struct platform_device *pdev) 1372static int aic3x_probe(struct platform_device *pdev)
@@ -1371,42 +1374,51 @@ static int aic3x_probe(struct platform_device *pdev)
1371 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1374 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1372 struct aic3x_setup_data *setup; 1375 struct aic3x_setup_data *setup;
1373 struct snd_soc_codec *codec; 1376 struct snd_soc_codec *codec;
1374 struct aic3x_priv *aic3x;
1375 int ret = 0; 1377 int ret = 0;
1376 1378
1377 printk(KERN_INFO "AIC3X Audio Codec %s\n", AIC3X_VERSION); 1379 codec = aic3x_codec;
1380 if (!codec) {
1381 dev_err(&pdev->dev, "Codec not registered\n");
1382 return -ENODEV;
1383 }
1378 1384
1385 socdev->card->codec = codec;
1379 setup = socdev->codec_data; 1386 setup = socdev->codec_data;
1380 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
1381 if (codec == NULL)
1382 return -ENOMEM;
1383 1387
1384 aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); 1388 if (setup) {
1385 if (aic3x == NULL) { 1389 /* setup GPIO functions */
1386 kfree(codec); 1390 aic3x_write(codec, AIC3X_GPIO1_REG,
1387 return -ENOMEM; 1391 (setup->gpio_func[0] & 0xf) << 4);
1392 aic3x_write(codec, AIC3X_GPIO2_REG,
1393 (setup->gpio_func[1] & 0xf) << 4);
1388 } 1394 }
1389 1395
1390 codec->private_data = aic3x; 1396 /* register pcms */
1391 socdev->card->codec = codec; 1397 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1392 mutex_init(&codec->mutex); 1398 if (ret < 0) {
1393 INIT_LIST_HEAD(&codec->dapm_widgets); 1399 printk(KERN_ERR "aic3x: failed to create pcms\n");
1394 INIT_LIST_HEAD(&codec->dapm_paths); 1400 goto pcm_err;
1395
1396 aic3x_socdev = socdev;
1397#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1398 if (setup->i2c_address) {
1399 codec->hw_write = (hw_write_t) i2c_master_send;
1400 ret = aic3x_add_i2c_device(pdev, setup);
1401 } 1401 }
1402#else
1403 /* Add other interfaces here */
1404#endif
1405 1402
1406 if (ret != 0) { 1403 snd_soc_add_controls(codec, aic3x_snd_controls,
1407 kfree(codec->private_data); 1404 ARRAY_SIZE(aic3x_snd_controls));
1408 kfree(codec); 1405
1406 aic3x_add_widgets(codec);
1407
1408 ret = snd_soc_init_card(socdev);
1409 if (ret < 0) {
1410 printk(KERN_ERR "aic3x: failed to register card\n");
1411 goto card_err;
1409 } 1412 }
1413
1414 return ret;
1415
1416card_err:
1417 snd_soc_free_pcms(socdev);
1418 snd_soc_dapm_free(socdev);
1419
1420pcm_err:
1421 kfree(codec->reg_cache);
1410 return ret; 1422 return ret;
1411} 1423}
1412 1424
@@ -1421,12 +1433,8 @@ static int aic3x_remove(struct platform_device *pdev)
1421 1433
1422 snd_soc_free_pcms(socdev); 1434 snd_soc_free_pcms(socdev);
1423 snd_soc_dapm_free(socdev); 1435 snd_soc_dapm_free(socdev);
1424#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1436
1425 i2c_unregister_device(codec->control_data); 1437 kfree(codec->reg_cache);
1426 i2c_del_driver(&aic3x_i2c_driver);
1427#endif
1428 kfree(codec->private_data);
1429 kfree(codec);
1430 1438
1431 return 0; 1439 return 0;
1432} 1440}
@@ -1441,13 +1449,15 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_aic3x);
1441 1449
1442static int __init aic3x_modinit(void) 1450static int __init aic3x_modinit(void)
1443{ 1451{
1444 return snd_soc_register_dai(&aic3x_dai); 1452 aic3x_i2c_init();
1453
1454 return 0;
1445} 1455}
1446module_init(aic3x_modinit); 1456module_init(aic3x_modinit);
1447 1457
1448static void __exit aic3x_exit(void) 1458static void __exit aic3x_exit(void)
1449{ 1459{
1450 snd_soc_unregister_dai(&aic3x_dai); 1460 aic3x_i2c_exit();
1451} 1461}
1452module_exit(aic3x_exit); 1462module_exit(aic3x_exit);
1453 1463
diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h
index ac827e578c4d..9af1c886213c 100644
--- a/sound/soc/codecs/tlv320aic3x.h
+++ b/sound/soc/codecs/tlv320aic3x.h
@@ -282,8 +282,6 @@ int aic3x_headset_detected(struct snd_soc_codec *codec);
282int aic3x_button_pressed(struct snd_soc_codec *codec); 282int aic3x_button_pressed(struct snd_soc_codec *codec);
283 283
284struct aic3x_setup_data { 284struct aic3x_setup_data {
285 int i2c_bus;
286 unsigned short i2c_address;
287 unsigned int gpio_func[2]; 285 unsigned int gpio_func[2];
288}; 286};
289 287
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index 4ded0e3a35e0..3f7e8a8b387e 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -63,6 +63,8 @@ struct wm8350_data {
63 struct wm8350_jack_data hpl; 63 struct wm8350_jack_data hpl;
64 struct wm8350_jack_data hpr; 64 struct wm8350_jack_data hpr;
65 struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; 65 struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
66 int fll_freq_out;
67 int fll_freq_in;
66}; 68};
67 69
68static unsigned int wm8350_codec_cache_read(struct snd_soc_codec *codec, 70static unsigned int wm8350_codec_cache_read(struct snd_soc_codec *codec,
@@ -610,7 +612,7 @@ SOC_DAPM_SINGLE("Switch", WM8350_BEEP_VOLUME, 15, 1, 1);
610 612
611/* Out4 Capture Mux */ 613/* Out4 Capture Mux */
612static const struct snd_kcontrol_new wm8350_out4_capture_controls = 614static const struct snd_kcontrol_new wm8350_out4_capture_controls =
613SOC_DAPM_ENUM("Route", wm8350_enum[8]); 615SOC_DAPM_ENUM("Route", wm8350_enum[7]);
614 616
615static const struct snd_soc_dapm_widget wm8350_dapm_widgets[] = { 617static const struct snd_soc_dapm_widget wm8350_dapm_widgets[] = {
616 618
@@ -1099,15 +1101,19 @@ static inline int fll_factors(struct _fll_div *fll_div, unsigned int input,
1099} 1101}
1100 1102
1101static int wm8350_set_fll(struct snd_soc_dai *codec_dai, 1103static int wm8350_set_fll(struct snd_soc_dai *codec_dai,
1102 int pll_id, unsigned int freq_in, 1104 int pll_id, int source, unsigned int freq_in,
1103 unsigned int freq_out) 1105 unsigned int freq_out)
1104{ 1106{
1105 struct snd_soc_codec *codec = codec_dai->codec; 1107 struct snd_soc_codec *codec = codec_dai->codec;
1106 struct wm8350 *wm8350 = codec->control_data; 1108 struct wm8350 *wm8350 = codec->control_data;
1109 struct wm8350_data *priv = codec->private_data;
1107 struct _fll_div fll_div; 1110 struct _fll_div fll_div;
1108 int ret = 0; 1111 int ret = 0;
1109 u16 fll_1, fll_4; 1112 u16 fll_1, fll_4;
1110 1113
1114 if (freq_in == priv->fll_freq_in && freq_out == priv->fll_freq_out)
1115 return 0;
1116
1111 /* power down FLL - we need to do this for reconfiguration */ 1117 /* power down FLL - we need to do this for reconfiguration */
1112 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, 1118 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4,
1113 WM8350_FLL_ENA | WM8350_FLL_OSC_ENA); 1119 WM8350_FLL_ENA | WM8350_FLL_OSC_ENA);
@@ -1142,6 +1148,9 @@ static int wm8350_set_fll(struct snd_soc_dai *codec_dai,
1142 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_OSC_ENA); 1148 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_OSC_ENA);
1143 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_ENA); 1149 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_ENA);
1144 1150
1151 priv->fll_freq_out = freq_out;
1152 priv->fll_freq_in = freq_in;
1153
1145 return 0; 1154 return 0;
1146} 1155}
1147 1156
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
index b9ef4d915221..9cb8e50f0fbb 100644
--- a/sound/soc/codecs/wm8400.c
+++ b/sound/soc/codecs/wm8400.c
@@ -1011,7 +1011,8 @@ static int fll_factors(struct wm8400_priv *wm8400, struct fll_factors *factors,
1011} 1011}
1012 1012
1013static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, 1013static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
1014 unsigned int freq_in, unsigned int freq_out) 1014 int source, unsigned int freq_in,
1015 unsigned int freq_out)
1015{ 1016{
1016 struct snd_soc_codec *codec = codec_dai->codec; 1017 struct snd_soc_codec *codec = codec_dai->codec;
1017 struct wm8400_priv *wm8400 = codec->private_data; 1018 struct wm8400_priv *wm8400 = codec->private_data;
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index 060d5d06ba95..5702435af81b 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -271,8 +271,8 @@ static void pll_factors(unsigned int target, unsigned int source)
271 pll_div.k = K; 271 pll_div.k = K;
272} 272}
273 273
274static int wm8510_set_dai_pll(struct snd_soc_dai *codec_dai, 274static int wm8510_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
275 int pll_id, unsigned int freq_in, unsigned int freq_out) 275 int source, unsigned int freq_in, unsigned int freq_out)
276{ 276{
277 struct snd_soc_codec *codec = codec_dai->codec; 277 struct snd_soc_codec *codec = codec_dai->codec;
278 u16 reg; 278 u16 reg;
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index d5473473a1e3..3be5c0b2552c 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -407,8 +407,8 @@ static int pll_factors(struct _pll_div *pll_div, unsigned int target,
407 return 0; 407 return 0;
408} 408}
409 409
410static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, 410static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
411 int pll_id, unsigned int freq_in, unsigned int freq_out) 411 int source, unsigned int freq_in, unsigned int freq_out)
412{ 412{
413 int offset; 413 int offset;
414 struct snd_soc_codec *codec = codec_dai->codec; 414 struct snd_soc_codec *codec = codec_dai->codec;
@@ -458,12 +458,12 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai,
458 return 0; 458 return 0;
459 459
460 snd_soc_write(codec, WM8580_PLLA1 + offset, pll_div.k & 0x1ff); 460 snd_soc_write(codec, WM8580_PLLA1 + offset, pll_div.k & 0x1ff);
461 snd_soc_write(codec, WM8580_PLLA2 + offset, (pll_div.k >> 9) & 0xff); 461 snd_soc_write(codec, WM8580_PLLA2 + offset, (pll_div.k >> 9) & 0x1ff);
462 snd_soc_write(codec, WM8580_PLLA3 + offset, 462 snd_soc_write(codec, WM8580_PLLA3 + offset,
463 (pll_div.k >> 18 & 0xf) | (pll_div.n << 4)); 463 (pll_div.k >> 18 & 0xf) | (pll_div.n << 4));
464 464
465 reg = snd_soc_read(codec, WM8580_PLLA4 + offset); 465 reg = snd_soc_read(codec, WM8580_PLLA4 + offset);
466 reg &= ~0x3f; 466 reg &= ~0x1b;
467 reg |= pll_div.prescale | pll_div.postscale << 1 | 467 reg |= pll_div.prescale | pll_div.postscale << 1 |
468 pll_div.freqmode << 3; 468 pll_div.freqmode << 3;
469 469
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index d80d414cfbbd..f60f3a02d1f8 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -723,8 +723,8 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int target,
723 pll_div->k = K; 723 pll_div->k = K;
724} 724}
725 725
726static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, 726static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
727 int pll_id, unsigned int freq_in, unsigned int freq_out) 727 int source, unsigned int freq_in, unsigned int freq_out)
728{ 728{
729 u16 reg, enable; 729 u16 reg, enable;
730 int offset; 730 int offset;
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index 5e9c855c0036..882604ef768c 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -814,8 +814,8 @@ reenable:
814 return 0; 814 return 0;
815} 815}
816 816
817static int wm8900_set_dai_pll(struct snd_soc_dai *codec_dai, 817static int wm8900_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
818 int pll_id, unsigned int freq_in, unsigned int freq_out) 818 int source, unsigned int freq_in, unsigned int freq_out)
819{ 819{
820 return wm8900_set_fll(codec_dai->codec, pll_id, freq_in, freq_out); 820 return wm8900_set_fll(codec_dai->codec, pll_id, freq_in, freq_out);
821} 821}
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index da97aae475a2..914d788a2b76 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -536,8 +536,8 @@ static void pll_factors(unsigned int target, unsigned int source)
536} 536}
537 537
538/* Untested at the moment */ 538/* Untested at the moment */
539static int wm8940_set_dai_pll(struct snd_soc_dai *codec_dai, 539static int wm8940_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
540 int pll_id, unsigned int freq_in, unsigned int freq_out) 540 int source, unsigned int freq_in, unsigned int freq_out)
541{ 541{
542 struct snd_soc_codec *codec = codec_dai->codec; 542 struct snd_soc_codec *codec = codec_dai->codec;
543 u16 reg; 543 u16 reg;
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index f59703be61c8..416fb3c17018 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -540,8 +540,8 @@ static int pll_factors(unsigned int source, unsigned int target,
540 return 0; 540 return 0;
541} 541}
542 542
543static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, 543static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
544 int pll_id, unsigned int freq_in, unsigned int freq_out) 544 int source, unsigned int freq_in, unsigned int freq_out)
545{ 545{
546 struct snd_soc_codec *codec = codec_dai->codec; 546 struct snd_soc_codec *codec = codec_dai->codec;
547 u16 reg; 547 u16 reg;
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
index d8a013ab3177..93d66e30f109 100644
--- a/sound/soc/codecs/wm8974.c
+++ b/sound/soc/codecs/wm8974.c
@@ -12,7 +12,6 @@
12 12
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/moduleparam.h> 14#include <linux/moduleparam.h>
15#include <linux/version.h>
16#include <linux/kernel.h> 15#include <linux/kernel.h>
17#include <linux/init.h> 16#include <linux/init.h>
18#include <linux/delay.h> 17#include <linux/delay.h>
@@ -329,8 +328,8 @@ static void pll_factors(unsigned int target, unsigned int source)
329 pll_div.k = K; 328 pll_div.k = K;
330} 329}
331 330
332static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai, 331static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
333 int pll_id, unsigned int freq_in, unsigned int freq_out) 332 int source, unsigned int freq_in, unsigned int freq_out)
334{ 333{
335 struct snd_soc_codec *codec = codec_dai->codec; 334 struct snd_soc_codec *codec = codec_dai->codec;
336 u16 reg; 335 u16 reg;
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index 2d702db4131d..f657e9a5fe26 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -972,8 +972,8 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int target,
972 pll_div->k = K; 972 pll_div->k = K;
973} 973}
974 974
975static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, 975static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
976 int pll_id, unsigned int freq_in, unsigned int freq_out) 976 int source, unsigned int freq_in, unsigned int freq_out)
977{ 977{
978 u16 reg; 978 u16 reg;
979 struct snd_soc_codec *codec = codec_dai->codec; 979 struct snd_soc_codec *codec = codec_dai->codec;
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index 13befa338247..6b32a2852603 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -422,7 +422,7 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
422 return 0; 422 return 0;
423} 423}
424 424
425static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, 425static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source,
426 unsigned int Fref, unsigned int Fout) 426 unsigned int Fref, unsigned int Fout)
427{ 427{
428 struct snd_soc_codec *codec = dai->codec; 428 struct snd_soc_codec *codec = dai->codec;
@@ -846,18 +846,76 @@ SOC_DAPM_SINGLE("Output Switch", WM8993_SPEAKER_MIXER, 2, 1, 0),
846SOC_DAPM_SINGLE("DAC Switch", WM8993_SPEAKER_MIXER, 0, 1, 0), 846SOC_DAPM_SINGLE("DAC Switch", WM8993_SPEAKER_MIXER, 0, 1, 0),
847}; 847};
848 848
849static const char *aif_text[] = {
850 "Left", "Right"
851};
852
853static const struct soc_enum aifoutl_enum =
854 SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_1, 15, 2, aif_text);
855
856static const struct snd_kcontrol_new aifoutl_mux =
857 SOC_DAPM_ENUM("AIFOUTL Mux", aifoutl_enum);
858
859static const struct soc_enum aifoutr_enum =
860 SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_1, 14, 2, aif_text);
861
862static const struct snd_kcontrol_new aifoutr_mux =
863 SOC_DAPM_ENUM("AIFOUTR Mux", aifoutr_enum);
864
865static const struct soc_enum aifinl_enum =
866 SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_2, 15, 2, aif_text);
867
868static const struct snd_kcontrol_new aifinl_mux =
869 SOC_DAPM_ENUM("AIFINL Mux", aifinl_enum);
870
871static const struct soc_enum aifinr_enum =
872 SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_2, 14, 2, aif_text);
873
874static const struct snd_kcontrol_new aifinr_mux =
875 SOC_DAPM_ENUM("AIFINR Mux", aifinr_enum);
876
877static const char *sidetone_text[] = {
878 "None", "Left", "Right"
879};
880
881static const struct soc_enum sidetonel_enum =
882 SOC_ENUM_SINGLE(WM8993_DIGITAL_SIDE_TONE, 2, 3, sidetone_text);
883
884static const struct snd_kcontrol_new sidetonel_mux =
885 SOC_DAPM_ENUM("Left Sidetone", sidetonel_enum);
886
887static const struct soc_enum sidetoner_enum =
888 SOC_ENUM_SINGLE(WM8993_DIGITAL_SIDE_TONE, 0, 3, sidetone_text);
889
890static const struct snd_kcontrol_new sidetoner_mux =
891 SOC_DAPM_ENUM("Right Sidetone", sidetoner_enum);
892
849static const struct snd_soc_dapm_widget wm8993_dapm_widgets[] = { 893static const struct snd_soc_dapm_widget wm8993_dapm_widgets[] = {
850SND_SOC_DAPM_SUPPLY("CLK_SYS", WM8993_BUS_CONTROL_1, 1, 0, clk_sys_event, 894SND_SOC_DAPM_SUPPLY("CLK_SYS", WM8993_BUS_CONTROL_1, 1, 0, clk_sys_event,
851 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 895 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
852SND_SOC_DAPM_SUPPLY("TOCLK", WM8993_CLOCKING_1, 14, 0, NULL, 0), 896SND_SOC_DAPM_SUPPLY("TOCLK", WM8993_CLOCKING_1, 14, 0, NULL, 0),
853SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8993_CLOCKING_3, 0, 0, NULL, 0), 897SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8993_CLOCKING_3, 0, 0, NULL, 0),
854 898
899SND_SOC_DAPM_ADC("ADCL", NULL, WM8993_POWER_MANAGEMENT_2, 1, 0),
900SND_SOC_DAPM_ADC("ADCR", NULL, WM8993_POWER_MANAGEMENT_2, 0, 0),
901
902SND_SOC_DAPM_MUX("AIFOUTL Mux", SND_SOC_NOPM, 0, 0, &aifoutl_mux),
903SND_SOC_DAPM_MUX("AIFOUTR Mux", SND_SOC_NOPM, 0, 0, &aifoutr_mux),
904
905SND_SOC_DAPM_AIF_OUT("AIFOUTL", "Capture", 0, SND_SOC_NOPM, 0, 0),
906SND_SOC_DAPM_AIF_OUT("AIFOUTR", "Capture", 1, SND_SOC_NOPM, 0, 0),
855 907
856SND_SOC_DAPM_ADC("ADCL", "Capture", WM8993_POWER_MANAGEMENT_2, 1, 0), 908SND_SOC_DAPM_AIF_IN("AIFINL", "Playback", 0, SND_SOC_NOPM, 0, 0),
857SND_SOC_DAPM_ADC("ADCR", "Capture", WM8993_POWER_MANAGEMENT_2, 0, 0), 909SND_SOC_DAPM_AIF_IN("AIFINR", "Playback", 1, SND_SOC_NOPM, 0, 0),
858 910
859SND_SOC_DAPM_DAC("DACL", "Playback", WM8993_POWER_MANAGEMENT_3, 1, 0), 911SND_SOC_DAPM_MUX("DACL Mux", SND_SOC_NOPM, 0, 0, &aifinl_mux),
860SND_SOC_DAPM_DAC("DACR", "Playback", WM8993_POWER_MANAGEMENT_3, 0, 0), 912SND_SOC_DAPM_MUX("DACR Mux", SND_SOC_NOPM, 0, 0, &aifinr_mux),
913
914SND_SOC_DAPM_MUX("DACL Sidetone", SND_SOC_NOPM, 0, 0, &sidetonel_mux),
915SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &sidetoner_mux),
916
917SND_SOC_DAPM_DAC("DACL", NULL, WM8993_POWER_MANAGEMENT_3, 1, 0),
918SND_SOC_DAPM_DAC("DACR", NULL, WM8993_POWER_MANAGEMENT_3, 0, 0),
861 919
862SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux), 920SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux),
863SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux), 921SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux),
@@ -875,10 +933,32 @@ static const struct snd_soc_dapm_route routes[] = {
875 { "ADCR", NULL, "CLK_SYS" }, 933 { "ADCR", NULL, "CLK_SYS" },
876 { "ADCR", NULL, "CLK_DSP" }, 934 { "ADCR", NULL, "CLK_DSP" },
877 935
936 { "AIFOUTL Mux", "Left", "ADCL" },
937 { "AIFOUTL Mux", "Right", "ADCR" },
938 { "AIFOUTR Mux", "Left", "ADCL" },
939 { "AIFOUTR Mux", "Right", "ADCR" },
940
941 { "AIFOUTL", NULL, "AIFOUTL Mux" },
942 { "AIFOUTR", NULL, "AIFOUTR Mux" },
943
944 { "DACL Mux", "Left", "AIFINL" },
945 { "DACL Mux", "Right", "AIFINR" },
946 { "DACR Mux", "Left", "AIFINL" },
947 { "DACR Mux", "Right", "AIFINR" },
948
949 { "DACL Sidetone", "Left", "ADCL" },
950 { "DACL Sidetone", "Right", "ADCR" },
951 { "DACR Sidetone", "Left", "ADCL" },
952 { "DACR Sidetone", "Right", "ADCR" },
953
878 { "DACL", NULL, "CLK_SYS" }, 954 { "DACL", NULL, "CLK_SYS" },
879 { "DACL", NULL, "CLK_DSP" }, 955 { "DACL", NULL, "CLK_DSP" },
956 { "DACL", NULL, "DACL Mux" },
957 { "DACL", NULL, "DACL Sidetone" },
880 { "DACR", NULL, "CLK_SYS" }, 958 { "DACR", NULL, "CLK_SYS" },
881 { "DACR", NULL, "CLK_DSP" }, 959 { "DACR", NULL, "CLK_DSP" },
960 { "DACR", NULL, "DACR Mux" },
961 { "DACR", NULL, "DACR Sidetone" },
882 962
883 { "Left Output Mixer", "DAC Switch", "DACL" }, 963 { "Left Output Mixer", "DAC Switch", "DACL" },
884 964
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c
index fa88b463e71f..e7d2840d9e59 100644
--- a/sound/soc/codecs/wm9705.c
+++ b/sound/soc/codecs/wm9705.c
@@ -406,7 +406,7 @@ static int wm9705_soc_probe(struct platform_device *pdev)
406 ret = snd_soc_init_card(socdev); 406 ret = snd_soc_init_card(socdev);
407 if (ret < 0) { 407 if (ret < 0) {
408 printk(KERN_ERR "wm9705: failed to register card\n"); 408 printk(KERN_ERR "wm9705: failed to register card\n");
409 goto pcm_err; 409 goto reset_err;
410 } 410 }
411 411
412 return 0; 412 return 0;
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index abed37acf787..ca3d449ed89e 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -800,8 +800,8 @@ static int wm9713_set_pll(struct snd_soc_codec *codec,
800 return 0; 800 return 0;
801} 801}
802 802
803static int wm9713_set_dai_pll(struct snd_soc_dai *codec_dai, 803static int wm9713_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
804 int pll_id, unsigned int freq_in, unsigned int freq_out) 804 int source, unsigned int freq_in, unsigned int freq_out)
805{ 805{
806 struct snd_soc_codec *codec = codec_dai->codec; 806 struct snd_soc_codec *codec = codec_dai->codec;
807 return wm9713_set_pll(codec, pll_id, freq_in, freq_out); 807 return wm9713_set_pll(codec, pll_id, freq_in, freq_out);
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index e8fc474ba5cf..e542027eea89 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -18,7 +18,6 @@
18#include <linux/pm.h> 18#include <linux/pm.h>
19#include <linux/i2c.h> 19#include <linux/i2c.h>
20#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/regulator/consumer.h>
22#include <sound/core.h> 21#include <sound/core.h>
23#include <sound/pcm.h> 22#include <sound/pcm.h>
24#include <sound/pcm_params.h> 23#include <sound/pcm_params.h>
@@ -274,17 +273,12 @@ static int hp_event(struct snd_soc_dapm_widget *w,
274 273
275 /* Start the DC servo */ 274 /* Start the DC servo */
276 snd_soc_update_bits(codec, WM8993_DC_SERVO_0, 275 snd_soc_update_bits(codec, WM8993_DC_SERVO_0,
277 WM8993_DCS_ENA_CHAN_0 | 276 0xFFFF,
278 WM8993_DCS_ENA_CHAN_1 |
279 WM8993_DCS_TRIG_STARTUP_1 |
280 WM8993_DCS_TRIG_STARTUP_0,
281 WM8993_DCS_ENA_CHAN_0 | 277 WM8993_DCS_ENA_CHAN_0 |
282 WM8993_DCS_ENA_CHAN_1 | 278 WM8993_DCS_ENA_CHAN_1 |
283 WM8993_DCS_TRIG_STARTUP_1 | 279 WM8993_DCS_TRIG_STARTUP_1 |
284 WM8993_DCS_TRIG_STARTUP_0); 280 WM8993_DCS_TRIG_STARTUP_0);
285 wait_for_dc_servo(codec); 281 wait_for_dc_servo(codec);
286 snd_soc_update_bits(codec, WM8993_DC_SERVO_1,
287 WM8993_DCS_TIMER_PERIOD_01_MASK, 0xa);
288 282
289 reg |= WM8993_HPOUT1R_OUTP | WM8993_HPOUT1R_RMV_SHORT | 283 reg |= WM8993_HPOUT1R_OUTP | WM8993_HPOUT1R_RMV_SHORT |
290 WM8993_HPOUT1L_OUTP | WM8993_HPOUT1L_RMV_SHORT; 284 WM8993_HPOUT1L_OUTP | WM8993_HPOUT1L_RMV_SHORT;
@@ -299,11 +293,8 @@ static int hp_event(struct snd_soc_dapm_widget *w,
299 WM8993_HPOUT1R_DLY | 293 WM8993_HPOUT1R_DLY |
300 WM8993_HPOUT1R_OUTP); 294 WM8993_HPOUT1R_OUTP);
301 295
302 snd_soc_update_bits(codec, WM8993_DC_SERVO_1,
303 WM8993_DCS_TIMER_PERIOD_01_MASK, 0);
304 snd_soc_update_bits(codec, WM8993_DC_SERVO_0, 296 snd_soc_update_bits(codec, WM8993_DC_SERVO_0,
305 WM8993_DCS_ENA_CHAN_0 | 297 0xffff, 0);
306 WM8993_DCS_ENA_CHAN_1, 0);
307 298
308 snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg); 299 snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg);
309 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, 300 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1,
@@ -474,12 +465,6 @@ SND_SOC_DAPM_MIXER("MIXINL", WM8993_POWER_MANAGEMENT_2, 9, 0,
474SND_SOC_DAPM_MIXER("MIXINR", WM8993_POWER_MANAGEMENT_2, 8, 0, 465SND_SOC_DAPM_MIXER("MIXINR", WM8993_POWER_MANAGEMENT_2, 8, 0,
475 mixinr, ARRAY_SIZE(mixinr)), 466 mixinr, ARRAY_SIZE(mixinr)),
476 467
477SND_SOC_DAPM_ADC("ADCL", "Capture", WM8993_POWER_MANAGEMENT_2, 1, 0),
478SND_SOC_DAPM_ADC("ADCR", "Capture", WM8993_POWER_MANAGEMENT_2, 0, 0),
479
480SND_SOC_DAPM_DAC("DACL", "Playback", WM8993_POWER_MANAGEMENT_3, 1, 0),
481SND_SOC_DAPM_DAC("DACR", "Playback", WM8993_POWER_MANAGEMENT_3, 0, 0),
482
483SND_SOC_DAPM_MIXER("Left Output Mixer", WM8993_POWER_MANAGEMENT_3, 5, 0, 468SND_SOC_DAPM_MIXER("Left Output Mixer", WM8993_POWER_MANAGEMENT_3, 5, 0,
484 left_output_mixer, ARRAY_SIZE(left_output_mixer)), 469 left_output_mixer, ARRAY_SIZE(left_output_mixer)),
485SND_SOC_DAPM_MIXER("Right Output Mixer", WM8993_POWER_MANAGEMENT_3, 4, 0, 470SND_SOC_DAPM_MIXER("Right Output Mixer", WM8993_POWER_MANAGEMENT_3, 4, 0,
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig
index 4dfd4ad9d90e..047ee39418c0 100644
--- a/sound/soc/davinci/Kconfig
+++ b/sound/soc/davinci/Kconfig
@@ -13,9 +13,9 @@ config SND_DAVINCI_SOC_MCASP
13 tristate 13 tristate
14 14
15config SND_DAVINCI_SOC_EVM 15config SND_DAVINCI_SOC_EVM
16 tristate "SoC Audio support for DaVinci DM6446 or DM355 EVM" 16 tristate "SoC Audio support for DaVinci DM6446, DM355 or DM365 EVM"
17 depends on SND_DAVINCI_SOC 17 depends on SND_DAVINCI_SOC
18 depends on MACH_DAVINCI_EVM || MACH_DAVINCI_DM355_EVM 18 depends on MACH_DAVINCI_EVM || MACH_DAVINCI_DM355_EVM || MACH_DAVINCI_DM365_EVM
19 select SND_DAVINCI_SOC_I2S 19 select SND_DAVINCI_SOC_I2S
20 select SND_SOC_TLV320AIC3X 20 select SND_SOC_TLV320AIC3X
21 help 21 help
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
index 46c1b0cb1d1b..7ccbe6684fc2 100644
--- a/sound/soc/davinci/davinci-evm.c
+++ b/sound/soc/davinci/davinci-evm.c
@@ -14,6 +14,7 @@
14#include <linux/timer.h> 14#include <linux/timer.h>
15#include <linux/interrupt.h> 15#include <linux/interrupt.h>
16#include <linux/platform_device.h> 16#include <linux/platform_device.h>
17#include <linux/i2c.h>
17#include <sound/core.h> 18#include <sound/core.h>
18#include <sound/pcm.h> 19#include <sound/pcm.h>
19#include <sound/soc.h> 20#include <sound/soc.h>
@@ -44,7 +45,8 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
44 unsigned sysclk; 45 unsigned sysclk;
45 46
46 /* ASP1 on DM355 EVM is clocked by an external oscillator */ 47 /* ASP1 on DM355 EVM is clocked by an external oscillator */
47 if (machine_is_davinci_dm355_evm() || machine_is_davinci_dm6467_evm()) 48 if (machine_is_davinci_dm355_evm() || machine_is_davinci_dm6467_evm() ||
49 machine_is_davinci_dm365_evm())
48 sysclk = 27000000; 50 sysclk = 27000000;
49 51
50 /* ASP0 in DM6446 EVM is clocked by U55, as configured by 52 /* ASP0 in DM6446 EVM is clocked by U55, as configured by
@@ -175,7 +177,7 @@ static struct snd_soc_dai_link da8xx_evm_dai = {
175 .ops = &evm_ops, 177 .ops = &evm_ops,
176}; 178};
177 179
178/* davinci-evm audio machine driver */ 180/* davinci dm6446, dm355 or dm365 evm audio machine driver */
179static struct snd_soc_card snd_soc_card_evm = { 181static struct snd_soc_card snd_soc_card_evm = {
180 .name = "DaVinci EVM", 182 .name = "DaVinci EVM",
181 .platform = &davinci_soc_platform, 183 .platform = &davinci_soc_platform,
@@ -205,48 +207,33 @@ static struct snd_soc_card da850_snd_soc_card = {
205 .num_links = 1, 207 .num_links = 1,
206}; 208};
207 209
208/* evm audio private data */ 210static struct aic3x_setup_data aic3x_setup;
209static struct aic3x_setup_data evm_aic3x_setup = {
210 .i2c_bus = 1,
211 .i2c_address = 0x1b,
212};
213
214/* dm6467 evm audio private data */
215static struct aic3x_setup_data dm6467_evm_aic3x_setup = {
216 .i2c_bus = 1,
217 .i2c_address = 0x18,
218};
219
220static struct aic3x_setup_data da8xx_evm_aic3x_setup = {
221 .i2c_bus = 1,
222 .i2c_address = 0x18,
223};
224 211
225/* evm audio subsystem */ 212/* evm audio subsystem */
226static struct snd_soc_device evm_snd_devdata = { 213static struct snd_soc_device evm_snd_devdata = {
227 .card = &snd_soc_card_evm, 214 .card = &snd_soc_card_evm,
228 .codec_dev = &soc_codec_dev_aic3x, 215 .codec_dev = &soc_codec_dev_aic3x,
229 .codec_data = &evm_aic3x_setup, 216 .codec_data = &aic3x_setup,
230}; 217};
231 218
232/* evm audio subsystem */ 219/* evm audio subsystem */
233static struct snd_soc_device dm6467_evm_snd_devdata = { 220static struct snd_soc_device dm6467_evm_snd_devdata = {
234 .card = &dm6467_snd_soc_card_evm, 221 .card = &dm6467_snd_soc_card_evm,
235 .codec_dev = &soc_codec_dev_aic3x, 222 .codec_dev = &soc_codec_dev_aic3x,
236 .codec_data = &dm6467_evm_aic3x_setup, 223 .codec_data = &aic3x_setup,
237}; 224};
238 225
239/* evm audio subsystem */ 226/* evm audio subsystem */
240static struct snd_soc_device da830_evm_snd_devdata = { 227static struct snd_soc_device da830_evm_snd_devdata = {
241 .card = &da830_snd_soc_card, 228 .card = &da830_snd_soc_card,
242 .codec_dev = &soc_codec_dev_aic3x, 229 .codec_dev = &soc_codec_dev_aic3x,
243 .codec_data = &da8xx_evm_aic3x_setup, 230 .codec_data = &aic3x_setup,
244}; 231};
245 232
246static struct snd_soc_device da850_evm_snd_devdata = { 233static struct snd_soc_device da850_evm_snd_devdata = {
247 .card = &da850_snd_soc_card, 234 .card = &da850_snd_soc_card,
248 .codec_dev = &soc_codec_dev_aic3x, 235 .codec_dev = &soc_codec_dev_aic3x,
249 .codec_data = &da8xx_evm_aic3x_setup, 236 .codec_data = &aic3x_setup,
250}; 237};
251 238
252static struct platform_device *evm_snd_device; 239static struct platform_device *evm_snd_device;
@@ -257,7 +244,7 @@ static int __init evm_init(void)
257 int index; 244 int index;
258 int ret; 245 int ret;
259 246
260 if (machine_is_davinci_evm()) { 247 if (machine_is_davinci_evm() || machine_is_davinci_dm365_evm()) {
261 evm_snd_dev_data = &evm_snd_devdata; 248 evm_snd_dev_data = &evm_snd_devdata;
262 index = 0; 249 index = 0;
263 } else if (machine_is_davinci_dm355_evm()) { 250 } else if (machine_is_davinci_dm355_evm()) {
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index eca22d7829d2..7a06c0a86665 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -512,34 +512,49 @@ static int davinci_config_channel_size(struct davinci_audio_dev *dev,
512 int channel_size) 512 int channel_size)
513{ 513{
514 u32 fmt = 0; 514 u32 fmt = 0;
515 u32 mask, rotate;
515 516
516 switch (channel_size) { 517 switch (channel_size) {
517 case DAVINCI_AUDIO_WORD_8: 518 case DAVINCI_AUDIO_WORD_8:
518 fmt = 0x03; 519 fmt = 0x03;
520 rotate = 6;
521 mask = 0x000000ff;
519 break; 522 break;
520 523
521 case DAVINCI_AUDIO_WORD_12: 524 case DAVINCI_AUDIO_WORD_12:
522 fmt = 0x05; 525 fmt = 0x05;
526 rotate = 5;
527 mask = 0x00000fff;
523 break; 528 break;
524 529
525 case DAVINCI_AUDIO_WORD_16: 530 case DAVINCI_AUDIO_WORD_16:
526 fmt = 0x07; 531 fmt = 0x07;
532 rotate = 4;
533 mask = 0x0000ffff;
527 break; 534 break;
528 535
529 case DAVINCI_AUDIO_WORD_20: 536 case DAVINCI_AUDIO_WORD_20:
530 fmt = 0x09; 537 fmt = 0x09;
538 rotate = 3;
539 mask = 0x000fffff;
531 break; 540 break;
532 541
533 case DAVINCI_AUDIO_WORD_24: 542 case DAVINCI_AUDIO_WORD_24:
534 fmt = 0x0B; 543 fmt = 0x0B;
544 rotate = 2;
545 mask = 0x00ffffff;
535 break; 546 break;
536 547
537 case DAVINCI_AUDIO_WORD_28: 548 case DAVINCI_AUDIO_WORD_28:
538 fmt = 0x0D; 549 fmt = 0x0D;
550 rotate = 1;
551 mask = 0x0fffffff;
539 break; 552 break;
540 553
541 case DAVINCI_AUDIO_WORD_32: 554 case DAVINCI_AUDIO_WORD_32:
542 fmt = 0x0F; 555 fmt = 0x0F;
556 rotate = 0;
557 mask = 0xffffffff;
543 break; 558 break;
544 559
545 default: 560 default:
@@ -550,6 +565,13 @@ static int davinci_config_channel_size(struct davinci_audio_dev *dev,
550 RXSSZ(fmt), RXSSZ(0x0F)); 565 RXSSZ(fmt), RXSSZ(0x0F));
551 mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, 566 mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
552 TXSSZ(fmt), TXSSZ(0x0F)); 567 TXSSZ(fmt), TXSSZ(0x0F));
568 mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXROT(rotate),
569 TXROT(7));
570 mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXROT(rotate),
571 RXROT(7));
572 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, mask);
573 mcasp_set_reg(dev->base + DAVINCI_MCASP_RXMASK_REG, mask);
574
553 return 0; 575 return 0;
554} 576}
555 577
@@ -638,7 +660,6 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
638 printk(KERN_ERR "playback tdm slot %d not supported\n", 660 printk(KERN_ERR "playback tdm slot %d not supported\n",
639 dev->tdm_slots); 661 dev->tdm_slots);
640 662
641 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, 0xFFFFFFFF);
642 mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); 663 mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
643 } else { 664 } else {
644 /* bit stream is MSB first with no delay */ 665 /* bit stream is MSB first with no delay */
@@ -655,7 +676,6 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
655 printk(KERN_ERR "capture tdm slot %d not supported\n", 676 printk(KERN_ERR "capture tdm slot %d not supported\n",
656 dev->tdm_slots); 677 dev->tdm_slots);
657 678
658 mcasp_set_reg(dev->base + DAVINCI_MCASP_RXMASK_REG, 0xFFFFFFFF);
659 mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); 679 mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
660 } 680 }
661} 681}
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c
index 9ff62e3a9b1d..6096d22283e6 100644
--- a/sound/soc/fsl/mpc5200_dma.c
+++ b/sound/soc/fsl/mpc5200_dma.c
@@ -447,6 +447,7 @@ int mpc5200_audio_dma_create(struct of_device *op)
447 int size, irq, rc; 447 int size, irq, rc;
448 const __be32 *prop; 448 const __be32 *prop;
449 void __iomem *regs; 449 void __iomem *regs;
450 int ret;
450 451
451 /* Fetch the registers and IRQ of the PSC */ 452 /* Fetch the registers and IRQ of the PSC */
452 irq = irq_of_parse_and_map(op->node, 0); 453 irq = irq_of_parse_and_map(op->node, 0);
@@ -463,14 +464,16 @@ int mpc5200_audio_dma_create(struct of_device *op)
463 /* Allocate and initialize the driver private data */ 464 /* Allocate and initialize the driver private data */
464 psc_dma = kzalloc(sizeof *psc_dma, GFP_KERNEL); 465 psc_dma = kzalloc(sizeof *psc_dma, GFP_KERNEL);
465 if (!psc_dma) { 466 if (!psc_dma) {
466 iounmap(regs); 467 ret = -ENOMEM;
467 return -ENOMEM; 468 goto out_unmap;
468 } 469 }
469 470
470 /* Get the PSC ID */ 471 /* Get the PSC ID */
471 prop = of_get_property(op->node, "cell-index", &size); 472 prop = of_get_property(op->node, "cell-index", &size);
472 if (!prop || size < sizeof *prop) 473 if (!prop || size < sizeof *prop) {
473 return -ENODEV; 474 ret = -ENODEV;
475 goto out_free;
476 }
474 477
475 spin_lock_init(&psc_dma->lock); 478 spin_lock_init(&psc_dma->lock);
476 mutex_init(&psc_dma->mutex); 479 mutex_init(&psc_dma->mutex);
@@ -493,9 +496,8 @@ int mpc5200_audio_dma_create(struct of_device *op)
493 if (!psc_dma->capture.bcom_task || 496 if (!psc_dma->capture.bcom_task ||
494 !psc_dma->playback.bcom_task) { 497 !psc_dma->playback.bcom_task) {
495 dev_err(&op->dev, "Could not allocate bestcomm tasks\n"); 498 dev_err(&op->dev, "Could not allocate bestcomm tasks\n");
496 iounmap(regs); 499 ret = -ENODEV;
497 kfree(psc_dma); 500 goto out_free;
498 return -ENODEV;
499 } 501 }
500 502
501 /* Disable all interrupts and reset the PSC */ 503 /* Disable all interrupts and reset the PSC */
@@ -537,12 +539,8 @@ int mpc5200_audio_dma_create(struct of_device *op)
537 &psc_dma_bcom_irq_tx, IRQF_SHARED, 539 &psc_dma_bcom_irq_tx, IRQF_SHARED,
538 "psc-dma-playback", &psc_dma->playback); 540 "psc-dma-playback", &psc_dma->playback);
539 if (rc) { 541 if (rc) {
540 free_irq(psc_dma->irq, psc_dma); 542 ret = -ENODEV;
541 free_irq(psc_dma->capture.irq, 543 goto out_irq;
542 &psc_dma->capture);
543 free_irq(psc_dma->playback.irq,
544 &psc_dma->playback);
545 return -ENODEV;
546 } 544 }
547 545
548 /* Save what we've done so it can be found again later */ 546 /* Save what we've done so it can be found again later */
@@ -550,6 +548,15 @@ int mpc5200_audio_dma_create(struct of_device *op)
550 548
551 /* Tell the ASoC OF helpers about it */ 549 /* Tell the ASoC OF helpers about it */
552 return snd_soc_register_platform(&mpc5200_audio_dma_platform); 550 return snd_soc_register_platform(&mpc5200_audio_dma_platform);
551out_irq:
552 free_irq(psc_dma->irq, psc_dma);
553 free_irq(psc_dma->capture.irq, &psc_dma->capture);
554 free_irq(psc_dma->playback.irq, &psc_dma->playback);
555out_free:
556 kfree(psc_dma);
557out_unmap:
558 iounmap(regs);
559 return ret;
553} 560}
554EXPORT_SYMBOL_GPL(mpc5200_audio_dma_create); 561EXPORT_SYMBOL_GPL(mpc5200_audio_dma_create);
555 562
diff --git a/sound/soc/imx/mx27vis_wm8974.c b/sound/soc/imx/mx27vis_wm8974.c
index e4dcb539108a..0267d2d91685 100644
--- a/sound/soc/imx/mx27vis_wm8974.c
+++ b/sound/soc/imx/mx27vis_wm8974.c
@@ -157,7 +157,7 @@ static int mx27vis_hifi_hw_params(struct snd_pcm_substream *substream,
157 157
158 158
159 /* codec PLL input is 25 MHz */ 159 /* codec PLL input is 25 MHz */
160 ret = codec_dai->ops->set_pll(codec_dai, IGNORED_ARG, 160 ret = codec_dai->ops->set_pll(codec_dai, IGNORED_ARG, IGNORED_ARG,
161 25000000, pll_out); 161 25000000, pll_out);
162 if (ret < 0) { 162 if (ret < 0) {
163 printk(KERN_ERR "Error when setting PLL input\n"); 163 printk(KERN_ERR "Error when setting PLL input\n");
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c
index b60b1dfbc435..0a505938e42b 100644
--- a/sound/soc/omap/n810.c
+++ b/sound/soc/omap/n810.c
@@ -22,6 +22,7 @@
22 */ 22 */
23 23
24#include <linux/clk.h> 24#include <linux/clk.h>
25#include <linux/i2c.h>
25#include <linux/platform_device.h> 26#include <linux/platform_device.h>
26#include <sound/core.h> 27#include <sound/core.h>
27#include <sound/pcm.h> 28#include <sound/pcm.h>
@@ -322,8 +323,6 @@ static struct snd_soc_card snd_soc_n810 = {
322 323
323/* Audio private data */ 324/* Audio private data */
324static struct aic3x_setup_data n810_aic33_setup = { 325static struct aic3x_setup_data n810_aic33_setup = {
325 .i2c_bus = 2,
326 .i2c_address = 0x18,
327 .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED, 326 .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED,
328 .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT, 327 .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT,
329}; 328};
@@ -337,6 +336,13 @@ static struct snd_soc_device n810_snd_devdata = {
337 336
338static struct platform_device *n810_snd_device; 337static struct platform_device *n810_snd_device;
339 338
339/* temporary i2c device creation until this can be moved into the machine
340 * support file.
341*/
342static struct i2c_board_info i2c_device[] = {
343 { I2C_BOARD_INFO("tlv320aic3x", 0x1b), }
344};
345
340static int __init n810_soc_init(void) 346static int __init n810_soc_init(void)
341{ 347{
342 int err; 348 int err;
@@ -345,6 +351,8 @@ static int __init n810_soc_init(void)
345 if (!(machine_is_nokia_n810() || machine_is_nokia_n810_wimax())) 351 if (!(machine_is_nokia_n810() || machine_is_nokia_n810_wimax()))
346 return -ENODEV; 352 return -ENODEV;
347 353
354 i2c_register_board_info(1, i2c_device, ARRAY_SIZE(i2c_device));
355
348 n810_snd_device = platform_device_alloc("soc-audio", -1); 356 n810_snd_device = platform_device_alloc("soc-audio", -1);
349 if (!n810_snd_device) 357 if (!n810_snd_device)
350 return -ENOMEM; 358 return -ENOMEM;
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 6a837ffd5d0b..3341f49402ca 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -139,27 +139,67 @@ static const unsigned long omap34xx_mcbsp_port[][2] = {
139static const unsigned long omap34xx_mcbsp_port[][2] = {}; 139static const unsigned long omap34xx_mcbsp_port[][2] = {};
140#endif 140#endif
141 141
142static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream)
143{
144 struct snd_soc_pcm_runtime *rtd = substream->private_data;
145 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
146 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
147 int dma_op_mode = omap_mcbsp_get_dma_op_mode(mcbsp_data->bus_id);
148 int samples;
149
150 /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
151 if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)
152 samples = snd_pcm_lib_period_bytes(substream) >> 1;
153 else
154 samples = 1;
155
156 /* Configure McBSP internal buffer usage */
157 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
158 omap_mcbsp_set_tx_threshold(mcbsp_data->bus_id, samples - 1);
159 else
160 omap_mcbsp_set_rx_threshold(mcbsp_data->bus_id, samples - 1);
161}
162
142static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, 163static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
143 struct snd_soc_dai *dai) 164 struct snd_soc_dai *dai)
144{ 165{
145 struct snd_soc_pcm_runtime *rtd = substream->private_data; 166 struct snd_soc_pcm_runtime *rtd = substream->private_data;
146 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 167 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
147 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 168 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
169 int bus_id = mcbsp_data->bus_id;
148 int err = 0; 170 int err = 0;
149 171
150 if (cpu_is_omap343x() && mcbsp_data->bus_id == 1) { 172 if (!cpu_dai->active)
173 err = omap_mcbsp_request(bus_id);
174
175 if (cpu_is_omap343x()) {
176 int dma_op_mode = omap_mcbsp_get_dma_op_mode(bus_id);
177 int max_period;
178
151 /* 179 /*
152 * McBSP2 in OMAP3 has 1024 * 32-bit internal audio buffer. 180 * McBSP2 in OMAP3 has 1024 * 32-bit internal audio buffer.
153 * Set constraint for minimum buffer size to the same than FIFO 181 * Set constraint for minimum buffer size to the same than FIFO
154 * size in order to avoid underruns in playback startup because 182 * size in order to avoid underruns in playback startup because
155 * HW is keeping the DMA request active until FIFO is filled. 183 * HW is keeping the DMA request active until FIFO is filled.
156 */ 184 */
157 snd_pcm_hw_constraint_minmax(substream->runtime, 185 if (bus_id == 1)
158 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4096, UINT_MAX); 186 snd_pcm_hw_constraint_minmax(substream->runtime,
159 } 187 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
188 4096, UINT_MAX);
160 189
161 if (!cpu_dai->active) 190 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
162 err = omap_mcbsp_request(mcbsp_data->bus_id); 191 max_period = omap_mcbsp_get_max_tx_threshold(bus_id);
192 else
193 max_period = omap_mcbsp_get_max_rx_threshold(bus_id);
194
195 max_period++;
196 max_period <<= 1;
197
198 if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)
199 snd_pcm_hw_constraint_minmax(substream->runtime,
200 SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
201 32, max_period);
202 }
163 203
164 return err; 204 return err;
165} 205}
@@ -215,7 +255,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
215 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 255 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
216 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; 256 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
217 int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id; 257 int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id;
218 int wlen, channels, wpf; 258 int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT;
219 unsigned long port; 259 unsigned long port;
220 unsigned int format; 260 unsigned int format;
221 261
@@ -231,6 +271,12 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
231 } else if (cpu_is_omap343x()) { 271 } else if (cpu_is_omap343x()) {
232 dma = omap24xx_dma_reqs[bus_id][substream->stream]; 272 dma = omap24xx_dma_reqs[bus_id][substream->stream];
233 port = omap34xx_mcbsp_port[bus_id][substream->stream]; 273 port = omap34xx_mcbsp_port[bus_id][substream->stream];
274 omap_mcbsp_dai_dma_params[id][substream->stream].set_threshold =
275 omap_mcbsp_set_threshold;
276 /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
277 if (omap_mcbsp_get_dma_op_mode(bus_id) ==
278 MCBSP_DMA_MODE_THRESHOLD)
279 sync_mode = OMAP_DMA_SYNC_FRAME;
234 } else { 280 } else {
235 return -ENODEV; 281 return -ENODEV;
236 } 282 }
@@ -238,6 +284,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
238 substream->stream ? "Audio Capture" : "Audio Playback"; 284 substream->stream ? "Audio Capture" : "Audio Playback";
239 omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma; 285 omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma;
240 omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port; 286 omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port;
287 omap_mcbsp_dai_dma_params[id][substream->stream].sync_mode = sync_mode;
241 cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream]; 288 cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream];
242 289
243 if (mcbsp_data->configured) { 290 if (mcbsp_data->configured) {
@@ -321,11 +368,14 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
321 /* Generic McBSP register settings */ 368 /* Generic McBSP register settings */
322 regs->spcr2 |= XINTM(3) | FREE; 369 regs->spcr2 |= XINTM(3) | FREE;
323 regs->spcr1 |= RINTM(3); 370 regs->spcr1 |= RINTM(3);
324 regs->rcr2 |= RFIG; 371 /* RFIG and XFIG are not defined in 34xx */
325 regs->xcr2 |= XFIG; 372 if (!cpu_is_omap34xx()) {
373 regs->rcr2 |= RFIG;
374 regs->xcr2 |= XFIG;
375 }
326 if (cpu_is_omap2430() || cpu_is_omap34xx()) { 376 if (cpu_is_omap2430() || cpu_is_omap34xx()) {
327 regs->xccr = DXENDLY(1) | XDMAEN; 377 regs->xccr = DXENDLY(1) | XDMAEN | XDISABLE;
328 regs->rccr = RFULL_CYCLE | RDMAEN; 378 regs->rccr = RFULL_CYCLE | RDMAEN | RDISABLE;
329 } 379 }
330 380
331 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 381 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -462,6 +512,40 @@ static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
462 return 0; 512 return 0;
463} 513}
464 514
515static int omap_mcbsp_dai_set_rcvr_src(struct omap_mcbsp_data *mcbsp_data,
516 int clk_id)
517{
518 int sel_bit, set = 0;
519 u16 reg = OMAP2_CONTROL_DEVCONF0;
520
521 if (cpu_class_is_omap1())
522 return -EINVAL; /* TODO: Can this be implemented for OMAP1? */
523 if (mcbsp_data->bus_id != 0)
524 return -EINVAL;
525
526 switch (clk_id) {
527 case OMAP_MCBSP_CLKR_SRC_CLKX:
528 set = 1;
529 case OMAP_MCBSP_CLKR_SRC_CLKR:
530 sel_bit = 3;
531 break;
532 case OMAP_MCBSP_FSR_SRC_FSX:
533 set = 1;
534 case OMAP_MCBSP_FSR_SRC_FSR:
535 sel_bit = 4;
536 break;
537 default:
538 return -EINVAL;
539 }
540
541 if (set)
542 omap_ctrl_writel(omap_ctrl_readl(reg) | (1 << sel_bit), reg);
543 else
544 omap_ctrl_writel(omap_ctrl_readl(reg) & ~(1 << sel_bit), reg);
545
546 return 0;
547}
548
465static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, 549static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
466 int clk_id, unsigned int freq, 550 int clk_id, unsigned int freq,
467 int dir) 551 int dir)
@@ -484,6 +568,13 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
484 case OMAP_MCBSP_SYSCLK_CLKR_EXT: 568 case OMAP_MCBSP_SYSCLK_CLKR_EXT:
485 regs->pcr0 |= SCLKME; 569 regs->pcr0 |= SCLKME;
486 break; 570 break;
571
572 case OMAP_MCBSP_CLKR_SRC_CLKR:
573 case OMAP_MCBSP_CLKR_SRC_CLKX:
574 case OMAP_MCBSP_FSR_SRC_FSR:
575 case OMAP_MCBSP_FSR_SRC_FSX:
576 err = omap_mcbsp_dai_set_rcvr_src(mcbsp_data, clk_id);
577 break;
487 default: 578 default:
488 err = -ENODEV; 579 err = -ENODEV;
489 } 580 }
diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h
index c8147aace813..647d2f981ab0 100644
--- a/sound/soc/omap/omap-mcbsp.h
+++ b/sound/soc/omap/omap-mcbsp.h
@@ -32,6 +32,10 @@ enum omap_mcbsp_clksrg_clk {
32 OMAP_MCBSP_SYSCLK_CLK, /* Internal ICLK */ 32 OMAP_MCBSP_SYSCLK_CLK, /* Internal ICLK */
33 OMAP_MCBSP_SYSCLK_CLKX_EXT, /* External CLKX pin */ 33 OMAP_MCBSP_SYSCLK_CLKX_EXT, /* External CLKX pin */
34 OMAP_MCBSP_SYSCLK_CLKR_EXT, /* External CLKR pin */ 34 OMAP_MCBSP_SYSCLK_CLKR_EXT, /* External CLKR pin */
35 OMAP_MCBSP_CLKR_SRC_CLKR, /* CLKR from CLKR pin */
36 OMAP_MCBSP_CLKR_SRC_CLKX, /* CLKR from CLKX pin */
37 OMAP_MCBSP_FSR_SRC_FSR, /* FSR from FSR pin */
38 OMAP_MCBSP_FSR_SRC_FSX, /* FSR from FSX pin */
35}; 39};
36 40
37/* McBSP dividers */ 41/* McBSP dividers */
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index 12e14c01068e..5735945788bf 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -162,7 +162,7 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
162 */ 162 */
163 dma_params.data_type = OMAP_DMA_DATA_TYPE_S16; 163 dma_params.data_type = OMAP_DMA_DATA_TYPE_S16;
164 dma_params.trigger = dma_data->dma_req; 164 dma_params.trigger = dma_data->dma_req;
165 dma_params.sync_mode = OMAP_DMA_SYNC_ELEMENT; 165 dma_params.sync_mode = dma_data->sync_mode;
166 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 166 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
167 dma_params.src_amode = OMAP_DMA_AMODE_POST_INC; 167 dma_params.src_amode = OMAP_DMA_AMODE_POST_INC;
168 dma_params.dst_amode = OMAP_DMA_AMODE_CONSTANT; 168 dma_params.dst_amode = OMAP_DMA_AMODE_CONSTANT;
@@ -195,6 +195,9 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
195 else 195 else
196 omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ); 196 omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ);
197 197
198 omap_set_dma_src_burst_mode(prtd->dma_ch, OMAP_DMA_DATA_BURST_16);
199 omap_set_dma_dest_burst_mode(prtd->dma_ch, OMAP_DMA_DATA_BURST_16);
200
198 return 0; 201 return 0;
199} 202}
200 203
@@ -202,6 +205,7 @@ static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
202{ 205{
203 struct snd_pcm_runtime *runtime = substream->runtime; 206 struct snd_pcm_runtime *runtime = substream->runtime;
204 struct omap_runtime_data *prtd = runtime->private_data; 207 struct omap_runtime_data *prtd = runtime->private_data;
208 struct omap_pcm_dma_data *dma_data = prtd->dma_data;
205 unsigned long flags; 209 unsigned long flags;
206 int ret = 0; 210 int ret = 0;
207 211
@@ -211,6 +215,10 @@ static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
211 case SNDRV_PCM_TRIGGER_RESUME: 215 case SNDRV_PCM_TRIGGER_RESUME:
212 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 216 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
213 prtd->period_index = 0; 217 prtd->period_index = 0;
218 /* Configure McBSP internal buffer usage */
219 if (dma_data->set_threshold)
220 dma_data->set_threshold(substream);
221
214 omap_start_dma(prtd->dma_ch); 222 omap_start_dma(prtd->dma_ch);
215 break; 223 break;
216 224
@@ -307,7 +315,7 @@ static struct snd_pcm_ops omap_pcm_ops = {
307 .mmap = omap_pcm_mmap, 315 .mmap = omap_pcm_mmap,
308}; 316};
309 317
310static u64 omap_pcm_dmamask = DMA_BIT_MASK(32); 318static u64 omap_pcm_dmamask = DMA_BIT_MASK(64);
311 319
312static int omap_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, 320static int omap_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
313 int stream) 321 int stream)
@@ -357,7 +365,7 @@ static int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
357 if (!card->dev->dma_mask) 365 if (!card->dev->dma_mask)
358 card->dev->dma_mask = &omap_pcm_dmamask; 366 card->dev->dma_mask = &omap_pcm_dmamask;
359 if (!card->dev->coherent_dma_mask) 367 if (!card->dev->coherent_dma_mask)
360 card->dev->coherent_dma_mask = DMA_BIT_MASK(32); 368 card->dev->coherent_dma_mask = DMA_BIT_MASK(64);
361 369
362 if (dai->playback.channels_min) { 370 if (dai->playback.channels_min) {
363 ret = omap_pcm_preallocate_dma_buffer(pcm, 371 ret = omap_pcm_preallocate_dma_buffer(pcm,
diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h
index 8d9d26916b05..38a821dd4118 100644
--- a/sound/soc/omap/omap-pcm.h
+++ b/sound/soc/omap/omap-pcm.h
@@ -29,6 +29,8 @@ struct omap_pcm_dma_data {
29 char *name; /* stream identifier */ 29 char *name; /* stream identifier */
30 int dma_req; /* DMA request line */ 30 int dma_req; /* DMA request line */
31 unsigned long port_addr; /* transmit/receive register */ 31 unsigned long port_addr; /* transmit/receive register */
32 int sync_mode; /* DMA sync mode */
33 void (*set_threshold)(struct snd_pcm_substream *substream);
32}; 34};
33 35
34extern struct snd_soc_platform omap_soc_platform; 36extern struct snd_soc_platform omap_soc_platform;
diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c
index f7e5b7488c35..4a3f62d1f295 100644
--- a/sound/soc/omap/sdp3430.c
+++ b/sound/soc/omap/sdp3430.c
@@ -40,8 +40,10 @@
40#include "omap-pcm.h" 40#include "omap-pcm.h"
41#include "../codecs/twl4030.h" 41#include "../codecs/twl4030.h"
42 42
43#define TWL4030_INTBR_PMBR1 0x0D 43/* TWL4030 PMBR1 Register */
44#define EXTMUTE(value) (value << 2) 44#define TWL4030_INTBR_PMBR1 0x0D
45/* TWL4030 PMBR1 Register GPIO6 mux bit */
46#define TWL4030_GPIO6_PWM0_MUTE(value) (value << 2)
45 47
46static struct snd_soc_card snd_soc_sdp3430; 48static struct snd_soc_card snd_soc_sdp3430;
47 49
@@ -299,6 +301,7 @@ static struct platform_device *sdp3430_snd_device;
299static int __init sdp3430_soc_init(void) 301static int __init sdp3430_soc_init(void)
300{ 302{
301 int ret; 303 int ret;
304 u8 pin_mux;
302 305
303 if (!machine_is_omap_3430sdp()) { 306 if (!machine_is_omap_3430sdp()) {
304 pr_debug("Not SDP3430!\n"); 307 pr_debug("Not SDP3430!\n");
@@ -318,8 +321,12 @@ static int __init sdp3430_soc_init(void)
318 *(unsigned int *)sdp3430_dai[1].cpu_dai->private_data = 2; /* McBSP3 */ 321 *(unsigned int *)sdp3430_dai[1].cpu_dai->private_data = 2; /* McBSP3 */
319 322
320 /* Set TWL4030 GPIO6 as EXTMUTE signal */ 323 /* Set TWL4030 GPIO6 as EXTMUTE signal */
321 twl4030_i2c_write_u8(TWL4030_MODULE_INTBR, EXTMUTE(0x02), 324 twl4030_i2c_read_u8(TWL4030_MODULE_INTBR, &pin_mux,
322 TWL4030_MODULE_INTBR); 325 TWL4030_INTBR_PMBR1);
326 pin_mux &= ~TWL4030_GPIO6_PWM0_MUTE(0x03);
327 pin_mux |= TWL4030_GPIO6_PWM0_MUTE(0x02);
328 twl4030_i2c_write_u8(TWL4030_MODULE_INTBR, pin_mux,
329 TWL4030_INTBR_PMBR1);
323 330
324 ret = platform_device_add(sdp3430_snd_device); 331 ret = platform_device_add(sdp3430_snd_device);
325 if (ret) 332 if (ret)
diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c
index 9f7c61e23daf..4c8d99a8d386 100644
--- a/sound/soc/pxa/magician.c
+++ b/sound/soc/pxa/magician.c
@@ -213,7 +213,7 @@ static int magician_playback_hw_params(struct snd_pcm_substream *substream,
213 return ret; 213 return ret;
214 214
215 /* set SSP audio pll clock */ 215 /* set SSP audio pll clock */
216 ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, acps); 216 ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, 0, acps);
217 if (ret < 0) 217 if (ret < 0)
218 return ret; 218 return ret;
219 219
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 5b9ed6464789..57f201c94ca8 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -305,8 +305,8 @@ static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
305/* 305/*
306 * Configure the PLL frequency pxa27x and (afaik - pxa320 only) 306 * Configure the PLL frequency pxa27x and (afaik - pxa320 only)
307 */ 307 */
308static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, 308static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id,
309 int pll_id, unsigned int freq_in, unsigned int freq_out) 309 int source, unsigned int freq_in, unsigned int freq_out)
310{ 310{
311 struct ssp_priv *priv = cpu_dai->private_data; 311 struct ssp_priv *priv = cpu_dai->private_data;
312 struct ssp_device *ssp = priv->dev.ssp; 312 struct ssp_device *ssp = priv->dev.ssp;
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index 7330e5c5b9df..e9ae7b3a7e00 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -251,8 +251,8 @@ static int __devinit pxa2xx_ac97_dev_probe(struct platform_device *pdev)
251 251
252 for (i = 0; i < ARRAY_SIZE(pxa_ac97_dai); i++) { 252 for (i = 0; i < ARRAY_SIZE(pxa_ac97_dai); i++) {
253 pxa_ac97_dai[i].dev = &pdev->dev; 253 pxa_ac97_dai[i].dev = &pdev->dev;
254 if (pdata && pdata->codec_pdata) 254 if (pdata && pdata->codec_pdata[0])
255 pxa_ac97_dai[i].ac97_pdata = pdata->codec_pdata; 255 pxa_ac97_dai[i].ac97_pdata = pdata->codec_pdata[0];
256 } 256 }
257 257
258 /* Punt most of the init to the SoC probe; we may need the machine 258 /* Punt most of the init to the SoC probe; we may need the machine
diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c
index 9a386b4c4ed1..dd678ae24398 100644
--- a/sound/soc/pxa/zylonite.c
+++ b/sound/soc/pxa/zylonite.c
@@ -74,7 +74,8 @@ static const struct snd_soc_dapm_route audio_map[] = {
74static int zylonite_wm9713_init(struct snd_soc_codec *codec) 74static int zylonite_wm9713_init(struct snd_soc_codec *codec)
75{ 75{
76 if (clk_pout) 76 if (clk_pout)
77 snd_soc_dai_set_pll(&codec->dai[0], 0, clk_get_rate(pout), 0); 77 snd_soc_dai_set_pll(&codec->dai[0], 0, 0,
78 clk_get_rate(pout), 0);
78 79
79 snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets, 80 snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets,
80 ARRAY_SIZE(zylonite_dapm_widgets)); 81 ARRAY_SIZE(zylonite_dapm_widgets));
@@ -128,7 +129,7 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream,
128 if (ret < 0) 129 if (ret < 0)
129 return ret; 130 return ret;
130 131
131 ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, pll_out); 132 ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, 0, pll_out);
132 if (ret < 0) 133 if (ret < 0)
133 return ret; 134 return ret;
134 135
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig
index 808de5c5caa7..d7912f1e4627 100644
--- a/sound/soc/s3c24xx/Kconfig
+++ b/sound/soc/s3c24xx/Kconfig
@@ -1,6 +1,7 @@
1config SND_S3C24XX_SOC 1config SND_S3C24XX_SOC
2 tristate "SoC Audio for the Samsung S3CXXXX chips" 2 tristate "SoC Audio for the Samsung S3CXXXX chips"
3 depends on ARCH_S3C2410 3 depends on ARCH_S3C2410 || ARCH_S3C64XX
4 select S3C64XX_DMA if ARCH_S3C64XX
4 help 5 help
5 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
6 the S3C24XX AC97 or I2S interfaces. You will also need to 7 the S3C24XX AC97 or I2S interfaces. You will also need to
@@ -55,6 +56,15 @@ config SND_S3C24XX_SOC_JIVE_WM8750
55 help 56 help
56 Sat Y if you want to add support for SoC audio on the Jive. 57 Sat Y if you want to add support for SoC audio on the Jive.
57 58
59config SND_S3C64XX_SOC_WM8580
60 tristate "SoC I2S Audio support for WM8580 on SMDK64XX"
61 depends on SND_S3C24XX_SOC && (MACH_SMDK6400 || MACH_SMDK6410)
62 depends on BROKEN
63 select SND_SOC_WM8580
64 select SND_S3C64XX_SOC_I2S
65 help
66 Sat Y if you want to add support for SoC audio on the SMDK64XX.
67
58config SND_S3C24XX_SOC_SMDK2443_WM9710 68config SND_S3C24XX_SOC_SMDK2443_WM9710
59 tristate "SoC AC97 Audio support for SMDK2443 - WM9710" 69 tristate "SoC AC97 Audio support for SMDK2443 - WM9710"
60 depends on SND_S3C24XX_SOC && MACH_SMDK2443 70 depends on SND_S3C24XX_SOC && MACH_SMDK2443
@@ -79,3 +89,22 @@ config SND_S3C24XX_SOC_S3C24XX_UDA134X
79 select SND_S3C24XX_SOC_I2S 89 select SND_S3C24XX_SOC_I2S
80 select SND_SOC_L3 90 select SND_SOC_L3
81 select SND_SOC_UDA134X 91 select SND_SOC_UDA134X
92
93config SND_S3C24XX_SOC_SIMTEC
94 tristate
95 help
96 Internal node for common S3C24XX/Simtec suppor
97
98config SND_S3C24XX_SOC_SIMTEC_TLV320AIC23
99 tristate "SoC I2S Audio support for TLV320AIC23 on Simtec boards"
100 depends on SND_S3C24XX_SOC && ARCH_S3C2410
101 select SND_S3C24XX_SOC_I2S
102 select SND_SOC_TLV320AIC23
103 select SND_S3C24XX_SOC_SIMTEC
104
105config SND_S3C24XX_SOC_SIMTEC_HERMES
106 tristate "SoC I2S Audio support for Simtec Hermes board"
107 depends on SND_S3C24XX_SOC && ARCH_S3C2410
108 select SND_S3C24XX_SOC_I2S
109 select SND_SOC_TLV320AIC3X
110 select SND_S3C24XX_SOC_SIMTEC
diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile
index eb219b016499..7790406f90b7 100644
--- a/sound/soc/s3c24xx/Makefile
+++ b/sound/soc/s3c24xx/Makefile
@@ -20,6 +20,10 @@ snd-soc-neo1973-gta02-wm8753-objs := neo1973_gta02_wm8753.o
20snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o 20snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o
21snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o 21snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o
22snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o 22snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o
23snd-soc-s3c24xx-simtec-objs := s3c24xx_simtec.o
24snd-soc-s3c24xx-simtec-hermes-objs := s3c24xx_simtec_hermes.o
25snd-soc-s3c24xx-simtec-tlv320aic23-objs := s3c24xx_simtec_tlv320aic23.o
26snd-soc-smdk64xx-wm8580-objs := smdk64xx_wm8580.o
23 27
24obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o 28obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o
25obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o 29obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
@@ -27,3 +31,8 @@ obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_GTA02_WM8753) += snd-soc-neo1973-gta02-wm87
27obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o 31obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o
28obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o 32obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o
29obj-$(CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o 33obj-$(CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o
34obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC) += snd-soc-s3c24xx-simtec.o
35obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_HERMES) += snd-soc-s3c24xx-simtec-hermes.o
36obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_TLV320AIC23) += snd-soc-s3c24xx-simtec-tlv320aic23.o
37obj-$(CONFIG_SND_S3C64XX_SOC_WM8580) += snd-soc-smdk64xx-wm8580.o
38
diff --git a/sound/soc/s3c24xx/neo1973_gta02_wm8753.c b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c
index 0c52e36ddd87..6ddd1b3b16b3 100644
--- a/sound/soc/s3c24xx/neo1973_gta02_wm8753.c
+++ b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c
@@ -119,7 +119,7 @@ static int neo1973_gta02_hifi_hw_params(struct snd_pcm_substream *substream,
119 return ret; 119 return ret;
120 120
121 /* codec PLL input is PCLK/4 */ 121 /* codec PLL input is PCLK/4 */
122 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 122 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0,
123 iis_clkrate / 4, pll_out); 123 iis_clkrate / 4, pll_out);
124 if (ret < 0) 124 if (ret < 0)
125 return ret; 125 return ret;
diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c
index 906709e6dd5f..16009eba9cba 100644
--- a/sound/soc/s3c24xx/neo1973_wm8753.c
+++ b/sound/soc/s3c24xx/neo1973_wm8753.c
@@ -137,7 +137,7 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
137 return ret; 137 return ret;
138 138
139 /* codec PLL input is PCLK/4 */ 139 /* codec PLL input is PCLK/4 */
140 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 140 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0,
141 iis_clkrate / 4, pll_out); 141 iis_clkrate / 4, pll_out);
142 if (ret < 0) 142 if (ret < 0)
143 return ret; 143 return ret;
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.c b/sound/soc/s3c24xx/s3c-i2s-v2.c
index 1a283170ca92..11c45a37c631 100644
--- a/sound/soc/s3c24xx/s3c-i2s-v2.c
+++ b/sound/soc/s3c24xx/s3c-i2s-v2.c
@@ -36,6 +36,7 @@
36#include <mach/dma.h> 36#include <mach/dma.h>
37 37
38#include "s3c-i2s-v2.h" 38#include "s3c-i2s-v2.h"
39#include "s3c24xx-pcm.h"
39 40
40#undef S3C_IIS_V2_SUPPORTED 41#undef S3C_IIS_V2_SUPPORTED
41 42
@@ -229,6 +230,8 @@ static void s3c2412_snd_rxctrl(struct s3c_i2sv2_info *i2s, int on)
229 pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic); 230 pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
230} 231}
231 232
233#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
234
232/* 235/*
233 * Wait for the LR signal to allow synchronisation to the L/R clock 236 * Wait for the LR signal to allow synchronisation to the L/R clock
234 * from the codec. May only be needed for slave mode. 237 * from the codec. May only be needed for slave mode.
@@ -236,19 +239,21 @@ static void s3c2412_snd_rxctrl(struct s3c_i2sv2_info *i2s, int on)
236static int s3c2412_snd_lrsync(struct s3c_i2sv2_info *i2s) 239static int s3c2412_snd_lrsync(struct s3c_i2sv2_info *i2s)
237{ 240{
238 u32 iiscon; 241 u32 iiscon;
239 unsigned long timeout = jiffies + msecs_to_jiffies(5); 242 unsigned long loops = msecs_to_loops(5);
240 243
241 pr_debug("Entered %s\n", __func__); 244 pr_debug("Entered %s\n", __func__);
242 245
243 while (1) { 246 while (--loops) {
244 iiscon = readl(i2s->regs + S3C2412_IISCON); 247 iiscon = readl(i2s->regs + S3C2412_IISCON);
245 if (iiscon & S3C2412_IISCON_LRINDEX) 248 if (iiscon & S3C2412_IISCON_LRINDEX)
246 break; 249 break;
247 250
248 if (timeout < jiffies) { 251 cpu_relax();
249 printk(KERN_ERR "%s: timeout\n", __func__); 252 }
250 return -ETIMEDOUT; 253
251 } 254 if (!loops) {
255 printk(KERN_ERR "%s: timeout\n", __func__);
256 return -ETIMEDOUT;
252 } 257 }
253 258
254 return 0; 259 return 0;
@@ -307,12 +312,15 @@ static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
307 312
308 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 313 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
309 case SND_SOC_DAIFMT_RIGHT_J: 314 case SND_SOC_DAIFMT_RIGHT_J:
315 iismod |= S3C2412_IISMOD_LR_RLOW;
310 iismod |= S3C2412_IISMOD_SDF_MSB; 316 iismod |= S3C2412_IISMOD_SDF_MSB;
311 break; 317 break;
312 case SND_SOC_DAIFMT_LEFT_J: 318 case SND_SOC_DAIFMT_LEFT_J:
319 iismod |= S3C2412_IISMOD_LR_RLOW;
313 iismod |= S3C2412_IISMOD_SDF_LSB; 320 iismod |= S3C2412_IISMOD_SDF_LSB;
314 break; 321 break;
315 case SND_SOC_DAIFMT_I2S: 322 case SND_SOC_DAIFMT_I2S:
323 iismod &= ~S3C2412_IISMOD_LR_RLOW;
316 iismod |= S3C2412_IISMOD_SDF_IIS; 324 iismod |= S3C2412_IISMOD_SDF_IIS;
317 break; 325 break;
318 default: 326 default:
@@ -357,19 +365,19 @@ static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
357#endif 365#endif
358 366
359#ifdef CONFIG_PLAT_S3C64XX 367#ifdef CONFIG_PLAT_S3C64XX
360 iismod &= ~0x606; 368 iismod &= ~(S3C64XX_IISMOD_BLC_MASK | S3C2412_IISMOD_BCLK_MASK);
361 /* Sample size */ 369 /* Sample size */
362 switch (params_format(params)) { 370 switch (params_format(params)) {
363 case SNDRV_PCM_FORMAT_S8: 371 case SNDRV_PCM_FORMAT_S8:
364 /* 8 bit sample, 16fs BCLK */ 372 /* 8 bit sample, 16fs BCLK */
365 iismod |= 0x2004; 373 iismod |= (S3C64XX_IISMOD_BLC_8BIT | S3C2412_IISMOD_BCLK_16FS);
366 break; 374 break;
367 case SNDRV_PCM_FORMAT_S16_LE: 375 case SNDRV_PCM_FORMAT_S16_LE:
368 /* 16 bit sample, 32fs BCLK */ 376 /* 16 bit sample, 32fs BCLK */
369 break; 377 break;
370 case SNDRV_PCM_FORMAT_S24_LE: 378 case SNDRV_PCM_FORMAT_S24_LE:
371 /* 24 bit sample, 48fs BCLK */ 379 /* 24 bit sample, 48fs BCLK */
372 iismod |= 0x4002; 380 iismod |= (S3C64XX_IISMOD_BLC_24BIT | S3C2412_IISMOD_BCLK_48FS);
373 break; 381 break;
374 } 382 }
375#endif 383#endif
@@ -387,6 +395,8 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
387 int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); 395 int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
388 unsigned long irqs; 396 unsigned long irqs;
389 int ret = 0; 397 int ret = 0;
398 int channel = ((struct s3c24xx_pcm_dma_params *)
399 rtd->dai->cpu_dai->dma_data)->channel;
390 400
391 pr_debug("Entered %s\n", __func__); 401 pr_debug("Entered %s\n", __func__);
392 402
@@ -416,6 +426,14 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
416 s3c2412_snd_txctrl(i2s, 1); 426 s3c2412_snd_txctrl(i2s, 1);
417 427
418 local_irq_restore(irqs); 428 local_irq_restore(irqs);
429
430 /*
431 * Load the next buffer to DMA to meet the reqirement
432 * of the auto reload mechanism of S3C24XX.
433 * This call won't bother S3C64XX.
434 */
435 s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED);
436
419 break; 437 break;
420 438
421 case SNDRV_PCM_TRIGGER_STOP: 439 case SNDRV_PCM_TRIGGER_STOP:
@@ -452,6 +470,31 @@ static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
452 470
453 switch (div_id) { 471 switch (div_id) {
454 case S3C_I2SV2_DIV_BCLK: 472 case S3C_I2SV2_DIV_BCLK:
473 if (div > 3) {
474 /* convert value to bit field */
475
476 switch (div) {
477 case 16:
478 div = S3C2412_IISMOD_BCLK_16FS;
479 break;
480
481 case 32:
482 div = S3C2412_IISMOD_BCLK_32FS;
483 break;
484
485 case 24:
486 div = S3C2412_IISMOD_BCLK_24FS;
487 break;
488
489 case 48:
490 div = S3C2412_IISMOD_BCLK_48FS;
491 break;
492
493 default:
494 return -EINVAL;
495 }
496 }
497
455 reg = readl(i2s->regs + S3C2412_IISMOD); 498 reg = readl(i2s->regs + S3C2412_IISMOD);
456 reg &= ~S3C2412_IISMOD_BCLK_MASK; 499 reg &= ~S3C2412_IISMOD_BCLK_MASK;
457 writel(reg | div, i2s->regs + S3C2412_IISMOD); 500 writel(reg | div, i2s->regs + S3C2412_IISMOD);
@@ -611,7 +654,7 @@ int s3c_i2sv2_probe(struct platform_device *pdev,
611 } 654 }
612 655
613 i2s->iis_pclk = clk_get(dev, "iis"); 656 i2s->iis_pclk = clk_get(dev, "iis");
614 if (i2s->iis_pclk == NULL) { 657 if (IS_ERR(i2s->iis_pclk)) {
615 dev_err(dev, "failed to get iis_clock\n"); 658 dev_err(dev, "failed to get iis_clock\n");
616 iounmap(i2s->regs); 659 iounmap(i2s->regs);
617 return -ENOENT; 660 return -ENOENT;
diff --git a/sound/soc/s3c24xx/s3c2443-ac97.c b/sound/soc/s3c24xx/s3c2443-ac97.c
index bf16f20fcbb3..fc1beb0930b9 100644
--- a/sound/soc/s3c24xx/s3c2443-ac97.c
+++ b/sound/soc/s3c24xx/s3c2443-ac97.c
@@ -290,6 +290,9 @@ static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
290 struct snd_soc_dai *dai) 290 struct snd_soc_dai *dai)
291{ 291{
292 u32 ac_glbctrl; 292 u32 ac_glbctrl;
293 struct snd_soc_pcm_runtime *rtd = substream->private_data;
294 int channel = ((struct s3c24xx_pcm_dma_params *)
295 rtd->dai->cpu_dai->dma_data)->channel;
293 296
294 ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); 297 ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
295 switch (cmd) { 298 switch (cmd) {
@@ -312,6 +315,8 @@ static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
312 } 315 }
313 writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); 316 writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
314 317
318 s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED);
319
315 return 0; 320 return 0;
316} 321}
317 322
@@ -334,6 +339,9 @@ static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream,
334 int cmd, struct snd_soc_dai *dai) 339 int cmd, struct snd_soc_dai *dai)
335{ 340{
336 u32 ac_glbctrl; 341 u32 ac_glbctrl;
342 struct snd_soc_pcm_runtime *rtd = substream->private_data;
343 int channel = ((struct s3c24xx_pcm_dma_params *)
344 rtd->dai->cpu_dai->dma_data)->channel;
337 345
338 ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); 346 ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
339 switch (cmd) { 347 switch (cmd) {
@@ -349,6 +357,8 @@ static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream,
349 } 357 }
350 writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); 358 writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
351 359
360 s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED);
361
352 return 0; 362 return 0;
353} 363}
354 364
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c
index 556e35f0ab73..40e2c4790f0d 100644
--- a/sound/soc/s3c24xx/s3c24xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c24xx-i2s.c
@@ -279,6 +279,9 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
279 struct snd_soc_dai *dai) 279 struct snd_soc_dai *dai)
280{ 280{
281 int ret = 0; 281 int ret = 0;
282 struct snd_soc_pcm_runtime *rtd = substream->private_data;
283 int channel = ((struct s3c24xx_pcm_dma_params *)
284 rtd->dai->cpu_dai->dma_data)->channel;
282 285
283 pr_debug("Entered %s\n", __func__); 286 pr_debug("Entered %s\n", __func__);
284 287
@@ -296,6 +299,8 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
296 s3c24xx_snd_rxctrl(1); 299 s3c24xx_snd_rxctrl(1);
297 else 300 else
298 s3c24xx_snd_txctrl(1); 301 s3c24xx_snd_txctrl(1);
302
303 s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED);
299 break; 304 break;
300 case SNDRV_PCM_TRIGGER_STOP: 305 case SNDRV_PCM_TRIGGER_STOP:
301 case SNDRV_PCM_TRIGGER_SUSPEND: 306 case SNDRV_PCM_TRIGGER_SUSPEND:
diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.c b/sound/soc/s3c24xx/s3c24xx-pcm.c
index eecfa5eba06b..5cbbdc80fde3 100644
--- a/sound/soc/s3c24xx/s3c24xx-pcm.c
+++ b/sound/soc/s3c24xx/s3c24xx-pcm.c
@@ -255,7 +255,6 @@ static int s3c24xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
255 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 255 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
256 prtd->state |= ST_RUNNING; 256 prtd->state |= ST_RUNNING;
257 s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_START); 257 s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_START);
258 s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_STARTED);
259 break; 258 break;
260 259
261 case SNDRV_PCM_TRIGGER_STOP: 260 case SNDRV_PCM_TRIGGER_STOP:
@@ -318,6 +317,7 @@ static int s3c24xx_pcm_open(struct snd_pcm_substream *substream)
318 317
319 pr_debug("Entered %s\n", __func__); 318 pr_debug("Entered %s\n", __func__);
320 319
320 snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
321 snd_soc_set_runtime_hwparams(substream, &s3c24xx_pcm_hardware); 321 snd_soc_set_runtime_hwparams(substream, &s3c24xx_pcm_hardware);
322 322
323 prtd = kzalloc(sizeof(struct s3c24xx_runtime_data), GFP_KERNEL); 323 prtd = kzalloc(sizeof(struct s3c24xx_runtime_data), GFP_KERNEL);
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec.c b/sound/soc/s3c24xx/s3c24xx_simtec.c
new file mode 100644
index 000000000000..1966e0d5652d
--- /dev/null
+++ b/sound/soc/s3c24xx/s3c24xx_simtec.c
@@ -0,0 +1,394 @@
1/* sound/soc/s3c24xx/s3c24xx_simtec.c
2 *
3 * Copyright 2009 Simtec Electronics
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8*/
9
10#include <linux/module.h>
11#include <linux/moduleparam.h>
12#include <linux/platform_device.h>
13#include <linux/gpio.h>
14#include <linux/clk.h>
15#include <linux/i2c.h>
16
17#include <sound/core.h>
18#include <sound/pcm.h>
19#include <sound/soc.h>
20#include <sound/soc-dapm.h>
21
22#include <plat/audio-simtec.h>
23
24#include "s3c24xx-pcm.h"
25#include "s3c24xx-i2s.h"
26#include "s3c24xx_simtec.h"
27
28static struct s3c24xx_audio_simtec_pdata *pdata;
29static struct clk *xtal_clk;
30
31static int spk_gain;
32static int spk_unmute;
33
34/**
35 * speaker_gain_get - read the speaker gain setting.
36 * @kcontrol: The control for the speaker gain.
37 * @ucontrol: The value that needs to be updated.
38 *
39 * Read the value for the AMP gain control.
40 */
41static int speaker_gain_get(struct snd_kcontrol *kcontrol,
42 struct snd_ctl_elem_value *ucontrol)
43{
44 ucontrol->value.integer.value[0] = spk_gain;
45 return 0;
46}
47
48/**
49 * speaker_gain_set - set the value of the speaker amp gain
50 * @value: The value to write.
51 */
52static void speaker_gain_set(int value)
53{
54 gpio_set_value_cansleep(pdata->amp_gain[0], value & 1);
55 gpio_set_value_cansleep(pdata->amp_gain[1], value >> 1);
56}
57
58/**
59 * speaker_gain_put - set the speaker gain setting.
60 * @kcontrol: The control for the speaker gain.
61 * @ucontrol: The value that needs to be set.
62 *
63 * Set the value of the speaker gain from the specified
64 * @ucontrol setting.
65 *
66 * Note, if the speaker amp is muted, then we do not set a gain value
67 * as at-least one of the ICs that is fitted will try and power up even
68 * if the main control is set to off.
69 */
70static int speaker_gain_put(struct snd_kcontrol *kcontrol,
71 struct snd_ctl_elem_value *ucontrol)
72{
73 int value = ucontrol->value.integer.value[0];
74
75 spk_gain = value;
76
77 if (!spk_unmute)
78 speaker_gain_set(value);
79
80 return 0;
81}
82
83static const struct snd_kcontrol_new amp_gain_controls[] = {
84 SOC_SINGLE_EXT("Speaker Gain", 0, 0, 3, 0,
85 speaker_gain_get, speaker_gain_put),
86};
87
88/**
89 * spk_unmute_state - set the unmute state of the speaker
90 * @to: zero to unmute, non-zero to ununmute.
91 */
92static void spk_unmute_state(int to)
93{
94 pr_debug("%s: to=%d\n", __func__, to);
95
96 spk_unmute = to;
97 gpio_set_value(pdata->amp_gpio, to);
98
99 /* if we're umuting, also re-set the gain */
100 if (to && pdata->amp_gain[0] > 0)
101 speaker_gain_set(spk_gain);
102}
103
104/**
105 * speaker_unmute_get - read the speaker unmute setting.
106 * @kcontrol: The control for the speaker gain.
107 * @ucontrol: The value that needs to be updated.
108 *
109 * Read the value for the AMP gain control.
110 */
111static int speaker_unmute_get(struct snd_kcontrol *kcontrol,
112 struct snd_ctl_elem_value *ucontrol)
113{
114 ucontrol->value.integer.value[0] = spk_unmute;
115 return 0;
116}
117
118/**
119 * speaker_unmute_put - set the speaker unmute setting.
120 * @kcontrol: The control for the speaker gain.
121 * @ucontrol: The value that needs to be set.
122 *
123 * Set the value of the speaker gain from the specified
124 * @ucontrol setting.
125 */
126static int speaker_unmute_put(struct snd_kcontrol *kcontrol,
127 struct snd_ctl_elem_value *ucontrol)
128{
129 spk_unmute_state(ucontrol->value.integer.value[0]);
130 return 0;
131}
132
133/* This is added as a manual control as the speaker amps create clicks
134 * when their power state is changed, which are far more noticeable than
135 * anything produced by the CODEC itself.
136 */
137static const struct snd_kcontrol_new amp_unmute_controls[] = {
138 SOC_SINGLE_EXT("Speaker Switch", 0, 0, 1, 0,
139 speaker_unmute_get, speaker_unmute_put),
140};
141
142void simtec_audio_init(struct snd_soc_codec *codec)
143{
144 if (pdata->amp_gpio > 0) {
145 pr_debug("%s: adding amp routes\n", __func__);
146
147 snd_soc_add_controls(codec, amp_unmute_controls,
148 ARRAY_SIZE(amp_unmute_controls));
149 }
150
151 if (pdata->amp_gain[0] > 0) {
152 pr_debug("%s: adding amp controls\n", __func__);
153 snd_soc_add_controls(codec, amp_gain_controls,
154 ARRAY_SIZE(amp_gain_controls));
155 }
156}
157EXPORT_SYMBOL_GPL(simtec_audio_init);
158
159#define CODEC_CLOCK 12000000
160
161/**
162 * simtec_hw_params - update hardware parameters
163 * @substream: The audio substream instance.
164 * @params: The parameters requested.
165 *
166 * Update the codec data routing and configuration settings
167 * from the supplied data.
168 */
169static int simtec_hw_params(struct snd_pcm_substream *substream,
170 struct snd_pcm_hw_params *params)
171{
172 struct snd_soc_pcm_runtime *rtd = substream->private_data;
173 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
174 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
175 int ret;
176
177 /* Set the CODEC as the bus clock master, I2S */
178 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
179 SND_SOC_DAIFMT_NB_NF |
180 SND_SOC_DAIFMT_CBM_CFM);
181 if (ret) {
182 pr_err("%s: failed set cpu dai format\n", __func__);
183 return ret;
184 }
185
186 /* Set the CODEC as the bus clock master */
187 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
188 SND_SOC_DAIFMT_NB_NF |
189 SND_SOC_DAIFMT_CBM_CFM);
190 if (ret) {
191 pr_err("%s: failed set codec dai format\n", __func__);
192 return ret;
193 }
194
195 ret = snd_soc_dai_set_sysclk(codec_dai, 0,
196 CODEC_CLOCK, SND_SOC_CLOCK_IN);
197 if (ret) {
198 pr_err( "%s: failed setting codec sysclk\n", __func__);
199 return ret;
200 }
201
202 if (pdata->use_mpllin) {
203 ret = snd_soc_dai_set_sysclk(cpu_dai, S3C24XX_CLKSRC_MPLL,
204 0, SND_SOC_CLOCK_OUT);
205
206 if (ret) {
207 pr_err("%s: failed to set MPLLin as clksrc\n",
208 __func__);
209 return ret;
210 }
211 }
212
213 if (pdata->output_cdclk) {
214 int cdclk_scale;
215
216 cdclk_scale = clk_get_rate(xtal_clk) / CODEC_CLOCK;
217 cdclk_scale--;
218
219 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
220 cdclk_scale);
221 }
222
223 return 0;
224}
225
226static int simtec_call_startup(struct s3c24xx_audio_simtec_pdata *pd)
227{
228 /* call any board supplied startup code, this currently only
229 * covers the bast/vr1000 which have a CPLD in the way of the
230 * LRCLK */
231 if (pd->startup)
232 pd->startup();
233
234 return 0;
235}
236
237static struct snd_soc_ops simtec_snd_ops = {
238 .hw_params = simtec_hw_params,
239};
240
241/**
242 * attach_gpio_amp - get and configure the necessary gpios
243 * @dev: The device we're probing.
244 * @pd: The platform data supplied by the board.
245 *
246 * If there is a GPIO based amplifier attached to the board, claim
247 * the necessary GPIO lines for it, and set default values.
248 */
249static int attach_gpio_amp(struct device *dev,
250 struct s3c24xx_audio_simtec_pdata *pd)
251{
252 int ret;
253
254 /* attach gpio amp gain (if any) */
255 if (pdata->amp_gain[0] > 0) {
256 ret = gpio_request(pd->amp_gain[0], "gpio-amp-gain0");
257 if (ret) {
258 dev_err(dev, "cannot get amp gpio gain0\n");
259 return ret;
260 }
261
262 ret = gpio_request(pd->amp_gain[1], "gpio-amp-gain1");
263 if (ret) {
264 dev_err(dev, "cannot get amp gpio gain1\n");
265 gpio_free(pdata->amp_gain[0]);
266 return ret;
267 }
268
269 gpio_direction_output(pd->amp_gain[0], 0);
270 gpio_direction_output(pd->amp_gain[1], 0);
271 }
272
273 /* note, curently we assume GPA0 isn't valid amp */
274 if (pdata->amp_gpio > 0) {
275 ret = gpio_request(pd->amp_gpio, "gpio-amp");
276 if (ret) {
277 dev_err(dev, "cannot get amp gpio %d (%d)\n",
278 pd->amp_gpio, ret);
279 goto err_amp;
280 }
281
282 /* set the amp off at startup */
283 spk_unmute_state(0);
284 }
285
286 return 0;
287
288err_amp:
289 if (pd->amp_gain[0] > 0) {
290 gpio_free(pd->amp_gain[0]);
291 gpio_free(pd->amp_gain[1]);
292 }
293
294 return ret;
295}
296
297static void detach_gpio_amp(struct s3c24xx_audio_simtec_pdata *pd)
298{
299 if (pd->amp_gain[0] > 0) {
300 gpio_free(pd->amp_gain[0]);
301 gpio_free(pd->amp_gain[1]);
302 }
303
304 if (pd->amp_gpio > 0)
305 gpio_free(pd->amp_gpio);
306}
307
308#ifdef CONFIG_PM
309int simtec_audio_resume(struct device *dev)
310{
311 simtec_call_startup(pdata);
312 return 0;
313}
314
315struct dev_pm_ops simtec_audio_pmops = {
316 .resume = simtec_audio_resume,
317};
318EXPORT_SYMBOL_GPL(simtec_audio_pmops);
319#endif
320
321int __devinit simtec_audio_core_probe(struct platform_device *pdev,
322 struct snd_soc_device *socdev)
323{
324 struct platform_device *snd_dev;
325 int ret;
326
327 socdev->card->dai_link->ops = &simtec_snd_ops;
328
329 pdata = pdev->dev.platform_data;
330 if (!pdata) {
331 dev_err(&pdev->dev, "no platform data supplied\n");
332 return -EINVAL;
333 }
334
335 simtec_call_startup(pdata);
336
337 xtal_clk = clk_get(&pdev->dev, "xtal");
338 if (IS_ERR(xtal_clk)) {
339 dev_err(&pdev->dev, "could not get clkout0\n");
340 return -EINVAL;
341 }
342
343 dev_info(&pdev->dev, "xtal rate is %ld\n", clk_get_rate(xtal_clk));
344
345 ret = attach_gpio_amp(&pdev->dev, pdata);
346 if (ret)
347 goto err_clk;
348
349 snd_dev = platform_device_alloc("soc-audio", -1);
350 if (!snd_dev) {
351 dev_err(&pdev->dev, "failed to alloc soc-audio devicec\n");
352 ret = -ENOMEM;
353 goto err_gpio;
354 }
355
356 platform_set_drvdata(snd_dev, socdev);
357 socdev->dev = &snd_dev->dev;
358
359 ret = platform_device_add(snd_dev);
360 if (ret) {
361 dev_err(&pdev->dev, "failed to add soc-audio dev\n");
362 goto err_pdev;
363 }
364
365 platform_set_drvdata(pdev, snd_dev);
366 return 0;
367
368err_pdev:
369 platform_device_put(snd_dev);
370
371err_gpio:
372 detach_gpio_amp(pdata);
373
374err_clk:
375 clk_put(xtal_clk);
376 return ret;
377}
378EXPORT_SYMBOL_GPL(simtec_audio_core_probe);
379
380int __devexit simtec_audio_remove(struct platform_device *pdev)
381{
382 struct platform_device *snd_dev = platform_get_drvdata(pdev);
383
384 platform_device_unregister(snd_dev);
385
386 detach_gpio_amp(pdata);
387 clk_put(xtal_clk);
388 return 0;
389}
390EXPORT_SYMBOL_GPL(simtec_audio_remove);
391
392MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
393MODULE_DESCRIPTION("ALSA SoC Simtec Audio common support");
394MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec.h b/sound/soc/s3c24xx/s3c24xx_simtec.h
new file mode 100644
index 000000000000..2714203af161
--- /dev/null
+++ b/sound/soc/s3c24xx/s3c24xx_simtec.h
@@ -0,0 +1,22 @@
1/* sound/soc/s3c24xx/s3c24xx_simtec.h
2 *
3 * Copyright 2009 Simtec Electronics
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8*/
9
10extern void simtec_audio_init(struct snd_soc_codec *codec);
11
12extern int simtec_audio_core_probe(struct platform_device *pdev,
13 struct snd_soc_device *socdev);
14
15extern int simtec_audio_remove(struct platform_device *pdev);
16
17#ifdef CONFIG_PM
18extern struct dev_pm_ops simtec_audio_pmops;
19#define simtec_audio_pm &simtec_audio_pmops
20#else
21#define simtec_audio_pm NULL
22#endif
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c b/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c
new file mode 100644
index 000000000000..8346bd96eaf5
--- /dev/null
+++ b/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c
@@ -0,0 +1,153 @@
1/* sound/soc/s3c24xx/s3c24xx_simtec_hermes.c
2 *
3 * Copyright 2009 Simtec Electronics
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8*/
9
10#include <linux/module.h>
11#include <linux/clk.h>
12#include <linux/platform_device.h>
13
14#include <sound/core.h>
15#include <sound/pcm.h>
16#include <sound/soc.h>
17#include <sound/soc-dapm.h>
18
19#include <plat/audio-simtec.h>
20
21#include "s3c24xx-pcm.h"
22#include "s3c24xx-i2s.h"
23#include "s3c24xx_simtec.h"
24
25#include "../codecs/tlv320aic3x.h"
26
27static const struct snd_soc_dapm_widget dapm_widgets[] = {
28 SND_SOC_DAPM_LINE("GSM Out", NULL),
29 SND_SOC_DAPM_LINE("GSM In", NULL),
30 SND_SOC_DAPM_LINE("Line In", NULL),
31 SND_SOC_DAPM_LINE("Line Out", NULL),
32 SND_SOC_DAPM_LINE("ZV", NULL),
33 SND_SOC_DAPM_MIC("Mic Jack", NULL),
34 SND_SOC_DAPM_HP("Headphone Jack", NULL),
35};
36
37static const struct snd_soc_dapm_route base_map[] = {
38 /* Headphone connected to HP{L,R}OUT and HP{L,R}COM */
39
40 { "Headphone Jack", NULL, "HPLOUT" },
41 { "Headphone Jack", NULL, "HPLCOM" },
42 { "Headphone Jack", NULL, "HPROUT" },
43 { "Headphone Jack", NULL, "HPRCOM" },
44
45 /* ZV connected to Line1 */
46
47 { "LINE1L", NULL, "ZV" },
48 { "LINE1R", NULL, "ZV" },
49
50 /* Line In connected to Line2 */
51
52 { "LINE2L", NULL, "Line In" },
53 { "LINE2R", NULL, "Line In" },
54
55 /* Microphone connected to MIC3R and MIC_BIAS */
56
57 { "MIC3L", NULL, "Mic Jack" },
58
59 /* GSM connected to MONO_LOUT and MIC3L (in) */
60
61 { "GSM Out", NULL, "MONO_LOUT" },
62 { "MIC3L", NULL, "GSM In" },
63
64 /* Speaker is connected to LINEOUT{LN,LP,RN,RP}, however we are
65 * not using the DAPM to power it up and down as there it makes
66 * a click when powering up. */
67};
68
69/**
70 * simtec_hermes_init - initialise and add controls
71 * @codec; The codec instance to attach to.
72 *
73 * Attach our controls and configure the necessary codec
74 * mappings for our sound card instance.
75*/
76static int simtec_hermes_init(struct snd_soc_codec *codec)
77{
78 snd_soc_dapm_new_controls(codec, dapm_widgets,
79 ARRAY_SIZE(dapm_widgets));
80
81 snd_soc_dapm_add_routes(codec, base_map, ARRAY_SIZE(base_map));
82
83 snd_soc_dapm_enable_pin(codec, "Headphone Jack");
84 snd_soc_dapm_enable_pin(codec, "Line In");
85 snd_soc_dapm_enable_pin(codec, "Line Out");
86 snd_soc_dapm_enable_pin(codec, "Mic Jack");
87
88 simtec_audio_init(codec);
89 snd_soc_dapm_sync(codec);
90
91 return 0;
92}
93
94static struct aic3x_setup_data codec_setup = {
95};
96
97static struct snd_soc_dai_link simtec_dai_aic33 = {
98 .name = "tlv320aic33",
99 .stream_name = "TLV320AIC33",
100 .cpu_dai = &s3c24xx_i2s_dai,
101 .codec_dai = &aic3x_dai,
102 .init = simtec_hermes_init,
103};
104
105/* simtec audio machine driver */
106static struct snd_soc_card snd_soc_machine_simtec_aic33 = {
107 .name = "Simtec-Hermes",
108 .platform = &s3c24xx_soc_platform,
109 .dai_link = &simtec_dai_aic33,
110 .num_links = 1,
111};
112
113/* simtec audio subsystem */
114static struct snd_soc_device simtec_snd_devdata_aic33 = {
115 .card = &snd_soc_machine_simtec_aic33,
116 .codec_dev = &soc_codec_dev_aic3x,
117 .codec_data = &codec_setup,
118};
119
120static int __devinit simtec_audio_hermes_probe(struct platform_device *pd)
121{
122 dev_info(&pd->dev, "probing....\n");
123 return simtec_audio_core_probe(pd, &simtec_snd_devdata_aic33);
124}
125
126static struct platform_driver simtec_audio_hermes_platdrv = {
127 .driver = {
128 .owner = THIS_MODULE,
129 .name = "s3c24xx-simtec-hermes-snd",
130 .pm = simtec_audio_pm,
131 },
132 .probe = simtec_audio_hermes_probe,
133 .remove = __devexit_p(simtec_audio_remove),
134};
135
136MODULE_ALIAS("platform:s3c24xx-simtec-hermes-snd");
137
138static int __init simtec_hermes_modinit(void)
139{
140 return platform_driver_register(&simtec_audio_hermes_platdrv);
141}
142
143static void __exit simtec_hermes_modexit(void)
144{
145 platform_driver_unregister(&simtec_audio_hermes_platdrv);
146}
147
148module_init(simtec_hermes_modinit);
149module_exit(simtec_hermes_modexit);
150
151MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
152MODULE_DESCRIPTION("ALSA SoC Simtec Audio support");
153MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c b/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c
new file mode 100644
index 000000000000..25797e096175
--- /dev/null
+++ b/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c
@@ -0,0 +1,137 @@
1/* sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c
2 *
3 * Copyright 2009 Simtec Electronics
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8*/
9
10#include <linux/module.h>
11#include <linux/clk.h>
12#include <linux/platform_device.h>
13
14#include <sound/core.h>
15#include <sound/pcm.h>
16#include <sound/soc.h>
17#include <sound/soc-dapm.h>
18
19#include <plat/audio-simtec.h>
20
21#include "s3c24xx-pcm.h"
22#include "s3c24xx-i2s.h"
23#include "s3c24xx_simtec.h"
24
25#include "../codecs/tlv320aic23.h"
26
27/* supported machines:
28 *
29 * Machine Connections AMP
30 * ------- ----------- ---
31 * BAST MIC, HPOUT, LOUT, LIN TPA2001D1 (HPOUTL,R) (gain hardwired)
32 * VR1000 HPOUT, LIN None
33 * VR2000 LIN, LOUT, MIC, HP LM4871 (HPOUTL,R)
34 * DePicture LIN, LOUT, MIC, HP LM4871 (HPOUTL,R)
35 * Anubis LIN, LOUT, MIC, HP TPA2001D1 (HPOUTL,R)
36 */
37
38static const struct snd_soc_dapm_widget dapm_widgets[] = {
39 SND_SOC_DAPM_HP("Headphone Jack", NULL),
40 SND_SOC_DAPM_LINE("Line In", NULL),
41 SND_SOC_DAPM_LINE("Line Out", NULL),
42 SND_SOC_DAPM_MIC("Mic Jack", NULL),
43};
44
45static const struct snd_soc_dapm_route base_map[] = {
46 { "Headphone Jack", NULL, "LHPOUT"},
47 { "Headphone Jack", NULL, "RHPOUT"},
48
49 { "Line Out", NULL, "LOUT" },
50 { "Line Out", NULL, "ROUT" },
51
52 { "LLINEIN", NULL, "Line In"},
53 { "RLINEIN", NULL, "Line In"},
54
55 { "MICIN", NULL, "Mic Jack"},
56};
57
58/**
59 * simtec_tlv320aic23_init - initialise and add controls
60 * @codec; The codec instance to attach to.
61 *
62 * Attach our controls and configure the necessary codec
63 * mappings for our sound card instance.
64*/
65static int simtec_tlv320aic23_init(struct snd_soc_codec *codec)
66{
67 snd_soc_dapm_new_controls(codec, dapm_widgets,
68 ARRAY_SIZE(dapm_widgets));
69
70 snd_soc_dapm_add_routes(codec, base_map, ARRAY_SIZE(base_map));
71
72 snd_soc_dapm_enable_pin(codec, "Headphone Jack");
73 snd_soc_dapm_enable_pin(codec, "Line In");
74 snd_soc_dapm_enable_pin(codec, "Line Out");
75 snd_soc_dapm_enable_pin(codec, "Mic Jack");
76
77 simtec_audio_init(codec);
78 snd_soc_dapm_sync(codec);
79
80 return 0;
81}
82
83static struct snd_soc_dai_link simtec_dai_aic23 = {
84 .name = "tlv320aic23",
85 .stream_name = "TLV320AIC23",
86 .cpu_dai = &s3c24xx_i2s_dai,
87 .codec_dai = &tlv320aic23_dai,
88 .init = simtec_tlv320aic23_init,
89};
90
91/* simtec audio machine driver */
92static struct snd_soc_card snd_soc_machine_simtec_aic23 = {
93 .name = "Simtec",
94 .platform = &s3c24xx_soc_platform,
95 .dai_link = &simtec_dai_aic23,
96 .num_links = 1,
97};
98
99/* simtec audio subsystem */
100static struct snd_soc_device simtec_snd_devdata_aic23 = {
101 .card = &snd_soc_machine_simtec_aic23,
102 .codec_dev = &soc_codec_dev_tlv320aic23,
103};
104
105static int __devinit simtec_audio_tlv320aic23_probe(struct platform_device *pd)
106{
107 return simtec_audio_core_probe(pd, &simtec_snd_devdata_aic23);
108}
109
110static struct platform_driver simtec_audio_tlv320aic23_platdrv = {
111 .driver = {
112 .owner = THIS_MODULE,
113 .name = "s3c24xx-simtec-tlv320aic23",
114 .pm = simtec_audio_pm,
115 },
116 .probe = simtec_audio_tlv320aic23_probe,
117 .remove = __devexit_p(simtec_audio_remove),
118};
119
120MODULE_ALIAS("platform:s3c24xx-simtec-tlv320aic23");
121
122static int __init simtec_tlv320aic23_modinit(void)
123{
124 return platform_driver_register(&simtec_audio_tlv320aic23_platdrv);
125}
126
127static void __exit simtec_tlv320aic23_modexit(void)
128{
129 platform_driver_unregister(&simtec_audio_tlv320aic23_platdrv);
130}
131
132module_init(simtec_tlv320aic23_modinit);
133module_exit(simtec_tlv320aic23_modexit);
134
135MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
136MODULE_DESCRIPTION("ALSA SoC Simtec Audio support");
137MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.c b/sound/soc/s3c24xx/s3c64xx-i2s.c
index 3c06c401d0fb..43fb253a3429 100644
--- a/sound/soc/s3c24xx/s3c64xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c64xx-i2s.c
@@ -99,6 +99,19 @@ static int s3c64xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
99 iismod |= S3C64XX_IISMOD_IMS_SYSMUX; 99 iismod |= S3C64XX_IISMOD_IMS_SYSMUX;
100 break; 100 break;
101 101
102 case S3C64XX_CLKSRC_CDCLK:
103 switch (dir) {
104 case SND_SOC_CLOCK_IN:
105 iismod |= S3C64XX_IISMOD_CDCLKCON;
106 break;
107 case SND_SOC_CLOCK_OUT:
108 iismod &= ~S3C64XX_IISMOD_CDCLKCON;
109 break;
110 default:
111 return -EINVAL;
112 }
113 break;
114
102 default: 115 default:
103 return -EINVAL; 116 return -EINVAL;
104 } 117 }
@@ -111,8 +124,12 @@ static int s3c64xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
111struct clk *s3c64xx_i2s_get_clock(struct snd_soc_dai *dai) 124struct clk *s3c64xx_i2s_get_clock(struct snd_soc_dai *dai)
112{ 125{
113 struct s3c_i2sv2_info *i2s = to_info(dai); 126 struct s3c_i2sv2_info *i2s = to_info(dai);
127 u32 iismod = readl(i2s->regs + S3C2412_IISMOD);
114 128
115 return i2s->iis_cclk; 129 if (iismod & S3C64XX_IISMOD_IMS_SYSMUX)
130 return i2s->iis_cclk;
131 else
132 return i2s->iis_pclk;
116} 133}
117EXPORT_SYMBOL_GPL(s3c64xx_i2s_get_clock); 134EXPORT_SYMBOL_GPL(s3c64xx_i2s_get_clock);
118 135
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.h b/sound/soc/s3c24xx/s3c64xx-i2s.h
index 02148cee2613..abe7253b55fc 100644
--- a/sound/soc/s3c24xx/s3c64xx-i2s.h
+++ b/sound/soc/s3c24xx/s3c64xx-i2s.h
@@ -25,6 +25,7 @@ struct clk;
25 25
26#define S3C64XX_CLKSRC_PCLK (0) 26#define S3C64XX_CLKSRC_PCLK (0)
27#define S3C64XX_CLKSRC_MUX (1) 27#define S3C64XX_CLKSRC_MUX (1)
28#define S3C64XX_CLKSRC_CDCLK (2)
28 29
29extern struct snd_soc_dai s3c64xx_i2s_dai[]; 30extern struct snd_soc_dai s3c64xx_i2s_dai[];
30 31
diff --git a/sound/soc/s3c24xx/smdk64xx_wm8580.c b/sound/soc/s3c24xx/smdk64xx_wm8580.c
new file mode 100644
index 000000000000..482aaf10eff6
--- /dev/null
+++ b/sound/soc/s3c24xx/smdk64xx_wm8580.c
@@ -0,0 +1,273 @@
1/*
2 * smdk64xx_wm8580.c
3 *
4 * Copyright (c) 2009 Samsung Electronics Co. Ltd
5 * Author: Jaswinder Singh <jassi.brar@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/platform_device.h>
14#include <linux/clk.h>
15#include <sound/core.h>
16#include <sound/pcm.h>
17#include <sound/pcm_params.h>
18#include <sound/soc.h>
19#include <sound/soc-dapm.h>
20
21#include "../codecs/wm8580.h"
22#include "s3c24xx-pcm.h"
23#include "s3c64xx-i2s.h"
24
25#define S3C64XX_I2S_V4 2
26
27/* SMDK64XX has a 12MHZ crystal attached to WM8580 */
28#define SMDK64XX_WM8580_FREQ 12000000
29
30static int smdk64xx_hw_params(struct snd_pcm_substream *substream,
31 struct snd_pcm_hw_params *params)
32{
33 struct snd_soc_pcm_runtime *rtd = substream->private_data;
34 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
35 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
36 unsigned int pll_out;
37 int bfs, rfs, ret;
38
39 switch (params_format(params)) {
40 case SNDRV_PCM_FORMAT_U8:
41 case SNDRV_PCM_FORMAT_S8:
42 bfs = 16;
43 break;
44 case SNDRV_PCM_FORMAT_U16_LE:
45 case SNDRV_PCM_FORMAT_S16_LE:
46 bfs = 32;
47 break;
48 default:
49 return -EINVAL;
50 }
51
52 /* The Fvco for WM8580 PLLs must fall within [90,100]MHz.
53 * This criterion can't be met if we request PLL output
54 * as {8000x256, 64000x256, 11025x256}Hz.
55 * As a wayout, we rather change rfs to a minimum value that
56 * results in (params_rate(params) * rfs), and itself, acceptable
57 * to both - the CODEC and the CPU.
58 */
59 switch (params_rate(params)) {
60 case 16000:
61 case 22050:
62 case 32000:
63 case 44100:
64 case 48000:
65 case 88200:
66 case 96000:
67 rfs = 256;
68 break;
69 case 64000:
70 rfs = 384;
71 break;
72 case 8000:
73 case 11025:
74 rfs = 512;
75 break;
76 default:
77 return -EINVAL;
78 }
79 pll_out = params_rate(params) * rfs;
80
81 /* Set the Codec DAI configuration */
82 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
83 | SND_SOC_DAIFMT_NB_NF
84 | SND_SOC_DAIFMT_CBM_CFM);
85 if (ret < 0)
86 return ret;
87
88 /* Set the AP DAI configuration */
89 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S
90 | SND_SOC_DAIFMT_NB_NF
91 | SND_SOC_DAIFMT_CBM_CFM);
92 if (ret < 0)
93 return ret;
94
95 ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_CDCLK,
96 0, SND_SOC_CLOCK_IN);
97 if (ret < 0)
98 return ret;
99
100 /* We use PCLK for basic ops in SoC-Slave mode */
101 ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_PCLK,
102 0, SND_SOC_CLOCK_IN);
103 if (ret < 0)
104 return ret;
105
106 /* Set WM8580 to drive MCLK from it's PLLA */
107 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_MCLK,
108 WM8580_CLKSRC_PLLA);
109 if (ret < 0)
110 return ret;
111
112 /* Explicitly set WM8580-DAC to source from MCLK */
113 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_DAC_CLKSEL,
114 WM8580_CLKSRC_MCLK);
115 if (ret < 0)
116 return ret;
117
118 /* Assuming the CODEC driver evaluates it's rfs too from this call */
119 ret = snd_soc_dai_set_pll(codec_dai, 0, WM8580_PLLA,
120 SMDK64XX_WM8580_FREQ, pll_out);
121 if (ret < 0)
122 return ret;
123
124 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C_I2SV2_DIV_BCLK, bfs);
125 if (ret < 0)
126 return ret;
127
128 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C_I2SV2_DIV_RCLK, rfs);
129 if (ret < 0)
130 return ret;
131
132 return 0;
133}
134
135/*
136 * SMDK64XX WM8580 DAI operations.
137 */
138static struct snd_soc_ops smdk64xx_ops = {
139 .hw_params = smdk64xx_hw_params,
140};
141
142/* SMDK64xx Playback widgets */
143static const struct snd_soc_dapm_widget wm8580_dapm_widgets_pbk[] = {
144 SND_SOC_DAPM_HP("Front-L/R", NULL),
145 SND_SOC_DAPM_HP("Center/Sub", NULL),
146 SND_SOC_DAPM_HP("Rear-L/R", NULL),
147};
148
149/* SMDK64xx Capture widgets */
150static const struct snd_soc_dapm_widget wm8580_dapm_widgets_cpt[] = {
151 SND_SOC_DAPM_MIC("MicIn", NULL),
152 SND_SOC_DAPM_LINE("LineIn", NULL),
153};
154
155/* SMDK-PAIFTX connections */
156static const struct snd_soc_dapm_route audio_map_tx[] = {
157 /* MicIn feeds AINL */
158 {"AINL", NULL, "MicIn"},
159
160 /* LineIn feeds AINL/R */
161 {"AINL", NULL, "LineIn"},
162 {"AINR", NULL, "LineIn"},
163};
164
165/* SMDK-PAIFRX connections */
166static const struct snd_soc_dapm_route audio_map_rx[] = {
167 /* Front Left/Right are fed VOUT1L/R */
168 {"Front-L/R", NULL, "VOUT1L"},
169 {"Front-L/R", NULL, "VOUT1R"},
170
171 /* Center/Sub are fed VOUT2L/R */
172 {"Center/Sub", NULL, "VOUT2L"},
173 {"Center/Sub", NULL, "VOUT2R"},
174
175 /* Rear Left/Right are fed VOUT3L/R */
176 {"Rear-L/R", NULL, "VOUT3L"},
177 {"Rear-L/R", NULL, "VOUT3R"},
178};
179
180static int smdk64xx_wm8580_init_paiftx(struct snd_soc_codec *codec)
181{
182 /* Add smdk64xx specific Capture widgets */
183 snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets_cpt,
184 ARRAY_SIZE(wm8580_dapm_widgets_cpt));
185
186 /* Set up PAIFTX audio path */
187 snd_soc_dapm_add_routes(codec, audio_map_tx, ARRAY_SIZE(audio_map_tx));
188
189 /* All enabled by default */
190 snd_soc_dapm_enable_pin(codec, "MicIn");
191 snd_soc_dapm_enable_pin(codec, "LineIn");
192
193 /* signal a DAPM event */
194 snd_soc_dapm_sync(codec);
195
196 return 0;
197}
198
199static int smdk64xx_wm8580_init_paifrx(struct snd_soc_codec *codec)
200{
201 /* Add smdk64xx specific Playback widgets */
202 snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets_pbk,
203 ARRAY_SIZE(wm8580_dapm_widgets_pbk));
204
205 /* Set up PAIFRX audio path */
206 snd_soc_dapm_add_routes(codec, audio_map_rx, ARRAY_SIZE(audio_map_rx));
207
208 /* All enabled by default */
209 snd_soc_dapm_enable_pin(codec, "Front-L/R");
210 snd_soc_dapm_enable_pin(codec, "Center/Sub");
211 snd_soc_dapm_enable_pin(codec, "Rear-L/R");
212
213 /* signal a DAPM event */
214 snd_soc_dapm_sync(codec);
215
216 return 0;
217}
218
219static struct snd_soc_dai_link smdk64xx_dai[] = {
220{ /* Primary Playback i/f */
221 .name = "WM8580 PAIF RX",
222 .stream_name = "Playback",
223 .cpu_dai = &s3c64xx_i2s_dai[S3C64XX_I2S_V4],
224 .codec_dai = &wm8580_dai[WM8580_DAI_PAIFRX],
225 .init = smdk64xx_wm8580_init_paifrx,
226 .ops = &smdk64xx_ops,
227},
228{ /* Primary Capture i/f */
229 .name = "WM8580 PAIF TX",
230 .stream_name = "Capture",
231 .cpu_dai = &s3c64xx_i2s_dai[S3C64XX_I2S_V4],
232 .codec_dai = &wm8580_dai[WM8580_DAI_PAIFTX],
233 .init = smdk64xx_wm8580_init_paiftx,
234 .ops = &smdk64xx_ops,
235},
236};
237
238static struct snd_soc_card smdk64xx = {
239 .name = "smdk64xx",
240 .platform = &s3c24xx_soc_platform,
241 .dai_link = smdk64xx_dai,
242 .num_links = ARRAY_SIZE(smdk64xx_dai),
243};
244
245static struct snd_soc_device smdk64xx_snd_devdata = {
246 .card = &smdk64xx,
247 .codec_dev = &soc_codec_dev_wm8580,
248};
249
250static struct platform_device *smdk64xx_snd_device;
251
252static int __init smdk64xx_audio_init(void)
253{
254 int ret;
255
256 smdk64xx_snd_device = platform_device_alloc("soc-audio", -1);
257 if (!smdk64xx_snd_device)
258 return -ENOMEM;
259
260 platform_set_drvdata(smdk64xx_snd_device, &smdk64xx_snd_devdata);
261 smdk64xx_snd_devdata.dev = &smdk64xx_snd_device->dev;
262 ret = platform_device_add(smdk64xx_snd_device);
263
264 if (ret)
265 platform_device_put(smdk64xx_snd_device);
266
267 return ret;
268}
269module_init(smdk64xx_audio_init);
270
271MODULE_AUTHOR("Jaswinder Singh, jassi.brar@samsung.com");
272MODULE_DESCRIPTION("ALSA SoC SMDK64XX WM8580");
273MODULE_LICENSE("GPL");
diff --git a/sound/soc/s6000/s6105-ipcam.c b/sound/soc/s6000/s6105-ipcam.c
index b5f95f9781c1..c1b40ac22c05 100644
--- a/sound/soc/s6000/s6105-ipcam.c
+++ b/sound/soc/s6000/s6105-ipcam.c
@@ -14,6 +14,7 @@
14#include <linux/timer.h> 14#include <linux/timer.h>
15#include <linux/interrupt.h> 15#include <linux/interrupt.h>
16#include <linux/platform_device.h> 16#include <linux/platform_device.h>
17#include <linux/i2c.h>
17#include <sound/core.h> 18#include <sound/core.h>
18#include <sound/pcm.h> 19#include <sound/pcm.h>
19#include <sound/soc.h> 20#include <sound/soc.h>
@@ -189,8 +190,6 @@ static struct snd_soc_card snd_soc_card_s6105 = {
189 190
190/* s6105 audio private data */ 191/* s6105 audio private data */
191static struct aic3x_setup_data s6105_aic3x_setup = { 192static struct aic3x_setup_data s6105_aic3x_setup = {
192 .i2c_bus = 0,
193 .i2c_address = 0x18,
194}; 193};
195 194
196/* s6105 audio subsystem */ 195/* s6105 audio subsystem */
@@ -211,10 +210,19 @@ static struct s6000_snd_platform_data __initdata s6105_snd_data = {
211 210
212static struct platform_device *s6105_snd_device; 211static struct platform_device *s6105_snd_device;
213 212
213/* temporary i2c device creation until this can be moved into the machine
214 * support file.
215*/
216static struct i2c_board_info i2c_device[] = {
217 { I2C_BOARD_INFO("tlv320aic33", 0x18), }
218};
219
214static int __init s6105_init(void) 220static int __init s6105_init(void)
215{ 221{
216 int ret; 222 int ret;
217 223
224 i2c_register_board_info(0, i2c_device, ARRAY_SIZE(i2c_device));
225
218 s6105_snd_device = platform_device_alloc("soc-audio", -1); 226 s6105_snd_device = platform_device_alloc("soc-audio", -1);
219 if (!s6105_snd_device) 227 if (!s6105_snd_device)
220 return -ENOMEM; 228 return -ENOMEM;
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
index 54bd604012af..9154b4363db3 100644
--- a/sound/soc/sh/Kconfig
+++ b/sound/soc/sh/Kconfig
@@ -20,7 +20,12 @@ config SND_SOC_SH4_HAC
20config SND_SOC_SH4_SSI 20config SND_SOC_SH4_SSI
21 tristate 21 tristate
22 22
23 23config SND_SOC_SH4_FSI
24 tristate "SH4 FSI support"
25 depends on CPU_SUBTYPE_SH7724
26 select SH_DMA
27 help
28 This option enables FSI sound support
24 29
25## 30##
26## Boards 31## Boards
@@ -35,4 +40,12 @@ config SND_SH7760_AC97
35 This option enables generic sound support for the first 40 This option enables generic sound support for the first
36 AC97 unit of the SH7760. 41 AC97 unit of the SH7760.
37 42
43config SND_FSI_AK4642
44 bool "FSI-AK4642 sound support"
45 depends on SND_SOC_SH4_FSI
46 select SND_SOC_AK4642
47 help
48 This option enables generic sound support for the
49 FSI - AK4642 unit
50
38endmenu 51endmenu
diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile
index a8e8ab81cc6a..a6997872f24e 100644
--- a/sound/soc/sh/Makefile
+++ b/sound/soc/sh/Makefile
@@ -5,10 +5,14 @@ obj-$(CONFIG_SND_SOC_PCM_SH7760) += snd-soc-dma-sh7760.o
5## audio units found on some SH-4 5## audio units found on some SH-4
6snd-soc-hac-objs := hac.o 6snd-soc-hac-objs := hac.o
7snd-soc-ssi-objs := ssi.o 7snd-soc-ssi-objs := ssi.o
8snd-soc-fsi-objs := fsi.o
8obj-$(CONFIG_SND_SOC_SH4_HAC) += snd-soc-hac.o 9obj-$(CONFIG_SND_SOC_SH4_HAC) += snd-soc-hac.o
9obj-$(CONFIG_SND_SOC_SH4_SSI) += snd-soc-ssi.o 10obj-$(CONFIG_SND_SOC_SH4_SSI) += snd-soc-ssi.o
11obj-$(CONFIG_SND_SOC_SH4_FSI) += snd-soc-fsi.o
10 12
11## boards 13## boards
12snd-soc-sh7760-ac97-objs := sh7760-ac97.o 14snd-soc-sh7760-ac97-objs := sh7760-ac97.o
15snd-soc-fsi-ak4642-objs := fsi-ak4642.o
13 16
14obj-$(CONFIG_SND_SH7760_AC97) += snd-soc-sh7760-ac97.o 17obj-$(CONFIG_SND_SH7760_AC97) += snd-soc-sh7760-ac97.o
18obj-$(CONFIG_SND_FSI_AK4642) += snd-soc-fsi-ak4642.o
diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c
new file mode 100644
index 000000000000..c7af09729c6e
--- /dev/null
+++ b/sound/soc/sh/fsi-ak4642.c
@@ -0,0 +1,107 @@
1/*
2 * FSI-AK464x sound support for ms7724se
3 *
4 * Copyright (C) 2009 Renesas Solutions Corp.
5 * Kuninori Morimoto <morimoto.kuninori@renesas.com>
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive
9 * for more details.
10 */
11
12#include <linux/module.h>
13#include <linux/moduleparam.h>
14#include <linux/platform_device.h>
15#include <linux/i2c.h>
16#include <linux/io.h>
17#include <sound/core.h>
18#include <sound/pcm.h>
19#include <sound/soc.h>
20#include <sound/soc-dapm.h>
21
22#include <sound/sh_fsi.h>
23#include <../sound/soc/codecs/ak4642.h>
24
25static struct snd_soc_dai_link fsi_dai_link = {
26 .name = "AK4642",
27 .stream_name = "AK4642",
28 .cpu_dai = &fsi_soc_dai[0], /* fsi */
29 .codec_dai = &ak4642_dai,
30 .ops = NULL,
31};
32
33static struct snd_soc_card fsi_soc_card = {
34 .name = "FSI",
35 .platform = &fsi_soc_platform,
36 .dai_link = &fsi_dai_link,
37 .num_links = 1,
38};
39
40static struct snd_soc_device fsi_snd_devdata = {
41 .card = &fsi_soc_card,
42 .codec_dev = &soc_codec_dev_ak4642,
43};
44
45#define AK4642_BUS 0
46#define AK4642_ADR 0x12
47static int ak4642_add_i2c_device(void)
48{
49 struct i2c_board_info info;
50 struct i2c_adapter *adapter;
51 struct i2c_client *client;
52
53 memset(&info, 0, sizeof(struct i2c_board_info));
54 info.addr = AK4642_ADR;
55 strlcpy(info.type, "ak4642", I2C_NAME_SIZE);
56
57 adapter = i2c_get_adapter(AK4642_BUS);
58 if (!adapter) {
59 printk(KERN_DEBUG "can't get i2c adapter\n");
60 return -ENODEV;
61 }
62
63 client = i2c_new_device(adapter, &info);
64 i2c_put_adapter(adapter);
65 if (!client) {
66 printk(KERN_DEBUG "can't add i2c device\n");
67 return -ENODEV;
68 }
69
70 return 0;
71}
72
73static struct platform_device *fsi_snd_device;
74
75static int __init fsi_ak4642_init(void)
76{
77 int ret = -ENOMEM;
78
79 ak4642_add_i2c_device();
80
81 fsi_snd_device = platform_device_alloc("soc-audio", -1);
82 if (!fsi_snd_device)
83 goto out;
84
85 platform_set_drvdata(fsi_snd_device,
86 &fsi_snd_devdata);
87 fsi_snd_devdata.dev = &fsi_snd_device->dev;
88 ret = platform_device_add(fsi_snd_device);
89
90 if (ret)
91 platform_device_put(fsi_snd_device);
92
93out:
94 return ret;
95}
96
97static void __exit fsi_ak4642_exit(void)
98{
99 platform_device_unregister(fsi_snd_device);
100}
101
102module_init(fsi_ak4642_init);
103module_exit(fsi_ak4642_exit);
104
105MODULE_LICENSE("GPL");
106MODULE_DESCRIPTION("Generic SH4 FSI-AK4642 sound card");
107MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>");
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
new file mode 100644
index 000000000000..44123248b630
--- /dev/null
+++ b/sound/soc/sh/fsi.c
@@ -0,0 +1,1004 @@
1/*
2 * Fifo-attached Serial Interface (FSI) support for SH7724
3 *
4 * Copyright (C) 2009 Renesas Solutions Corp.
5 * Kuninori Morimoto <morimoto.kuninori@renesas.com>
6 *
7 * Based on ssi.c
8 * Copyright (c) 2007 Manuel Lauss <mano@roarinelk.homelinux.net>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/init.h>
16#include <linux/module.h>
17#include <linux/platform_device.h>
18#include <linux/delay.h>
19#include <linux/list.h>
20#include <linux/clk.h>
21#include <linux/io.h>
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/initval.h>
25#include <sound/soc.h>
26#include <sound/pcm_params.h>
27#include <sound/sh_fsi.h>
28#include <asm/atomic.h>
29#include <asm/dma.h>
30#include <asm/dma-sh.h>
31
32#define DO_FMT 0x0000
33#define DOFF_CTL 0x0004
34#define DOFF_ST 0x0008
35#define DI_FMT 0x000C
36#define DIFF_CTL 0x0010
37#define DIFF_ST 0x0014
38#define CKG1 0x0018
39#define CKG2 0x001C
40#define DIDT 0x0020
41#define DODT 0x0024
42#define MUTE_ST 0x0028
43#define REG_END MUTE_ST
44
45#define INT_ST 0x0200
46#define IEMSK 0x0204
47#define IMSK 0x0208
48#define MUTE 0x020C
49#define CLK_RST 0x0210
50#define SOFT_RST 0x0214
51#define MREG_START INT_ST
52#define MREG_END SOFT_RST
53
54/* DO_FMT */
55/* DI_FMT */
56#define CR_FMT(param) ((param) << 4)
57# define CR_MONO 0x0
58# define CR_MONO_D 0x1
59# define CR_PCM 0x2
60# define CR_I2S 0x3
61# define CR_TDM 0x4
62# define CR_TDM_D 0x5
63
64/* DOFF_CTL */
65/* DIFF_CTL */
66#define IRQ_HALF 0x00100000
67#define FIFO_CLR 0x00000001
68
69/* DOFF_ST */
70#define ERR_OVER 0x00000010
71#define ERR_UNDER 0x00000001
72
73/* CLK_RST */
74#define B_CLK 0x00000010
75#define A_CLK 0x00000001
76
77/* INT_ST */
78#define INT_B_IN (1 << 12)
79#define INT_B_OUT (1 << 8)
80#define INT_A_IN (1 << 4)
81#define INT_A_OUT (1 << 0)
82
83#define FSI_RATES SNDRV_PCM_RATE_8000_96000
84
85#define FSI_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
86
87/************************************************************************
88
89
90 struct
91
92
93************************************************************************/
94struct fsi_priv {
95 void __iomem *base;
96 struct snd_pcm_substream *substream;
97
98 int fifo_max;
99 int chan;
100 int dma_chan;
101
102 int byte_offset;
103 int period_len;
104 int buffer_len;
105 int periods;
106};
107
108struct fsi_master {
109 void __iomem *base;
110 int irq;
111 struct clk *clk;
112 struct fsi_priv fsia;
113 struct fsi_priv fsib;
114 struct sh_fsi_platform_info *info;
115};
116
117static struct fsi_master *master;
118
119/************************************************************************
120
121
122 basic read write function
123
124
125************************************************************************/
126static int __fsi_reg_write(u32 reg, u32 data)
127{
128 /* valid data area is 24bit */
129 data &= 0x00ffffff;
130
131 return ctrl_outl(data, reg);
132}
133
134static u32 __fsi_reg_read(u32 reg)
135{
136 return ctrl_inl(reg);
137}
138
139static int __fsi_reg_mask_set(u32 reg, u32 mask, u32 data)
140{
141 u32 val = __fsi_reg_read(reg);
142
143 val &= ~mask;
144 val |= data & mask;
145
146 return __fsi_reg_write(reg, val);
147}
148
149static int fsi_reg_write(struct fsi_priv *fsi, u32 reg, u32 data)
150{
151 if (reg > REG_END)
152 return -1;
153
154 return __fsi_reg_write((u32)(fsi->base + reg), data);
155}
156
157static u32 fsi_reg_read(struct fsi_priv *fsi, u32 reg)
158{
159 if (reg > REG_END)
160 return 0;
161
162 return __fsi_reg_read((u32)(fsi->base + reg));
163}
164
165static int fsi_reg_mask_set(struct fsi_priv *fsi, u32 reg, u32 mask, u32 data)
166{
167 if (reg > REG_END)
168 return -1;
169
170 return __fsi_reg_mask_set((u32)(fsi->base + reg), mask, data);
171}
172
173static int fsi_master_write(u32 reg, u32 data)
174{
175 if ((reg < MREG_START) ||
176 (reg > MREG_END))
177 return -1;
178
179 return __fsi_reg_write((u32)(master->base + reg), data);
180}
181
182static u32 fsi_master_read(u32 reg)
183{
184 if ((reg < MREG_START) ||
185 (reg > MREG_END))
186 return 0;
187
188 return __fsi_reg_read((u32)(master->base + reg));
189}
190
191static int fsi_master_mask_set(u32 reg, u32 mask, u32 data)
192{
193 if ((reg < MREG_START) ||
194 (reg > MREG_END))
195 return -1;
196
197 return __fsi_reg_mask_set((u32)(master->base + reg), mask, data);
198}
199
200/************************************************************************
201
202
203 basic function
204
205
206************************************************************************/
207static struct fsi_priv *fsi_get(struct snd_pcm_substream *substream)
208{
209 struct snd_soc_pcm_runtime *rtd;
210 struct fsi_priv *fsi = NULL;
211
212 if (!substream || !master)
213 return NULL;
214
215 rtd = substream->private_data;
216 switch (rtd->dai->cpu_dai->id) {
217 case 0:
218 fsi = &master->fsia;
219 break;
220 case 1:
221 fsi = &master->fsib;
222 break;
223 }
224
225 return fsi;
226}
227
228static int fsi_is_port_a(struct fsi_priv *fsi)
229{
230 /* return
231 * 1 : port a
232 * 0 : port b
233 */
234
235 if (fsi == &master->fsia)
236 return 1;
237
238 return 0;
239}
240
241static u32 fsi_get_info_flags(struct fsi_priv *fsi)
242{
243 int is_porta = fsi_is_port_a(fsi);
244
245 return is_porta ? master->info->porta_flags :
246 master->info->portb_flags;
247}
248
249static int fsi_is_master_mode(struct fsi_priv *fsi, int is_play)
250{
251 u32 mode;
252 u32 flags = fsi_get_info_flags(fsi);
253
254 mode = is_play ? SH_FSI_OUT_SLAVE_MODE : SH_FSI_IN_SLAVE_MODE;
255
256 /* return
257 * 1 : master mode
258 * 0 : slave mode
259 */
260
261 return (mode & flags) != mode;
262}
263
264static u32 fsi_port_ab_io_bit(struct fsi_priv *fsi, int is_play)
265{
266 int is_porta = fsi_is_port_a(fsi);
267 u32 data;
268
269 if (is_porta)
270 data = is_play ? (1 << 0) : (1 << 4);
271 else
272 data = is_play ? (1 << 8) : (1 << 12);
273
274 return data;
275}
276
277static void fsi_stream_push(struct fsi_priv *fsi,
278 struct snd_pcm_substream *substream,
279 u32 buffer_len,
280 u32 period_len)
281{
282 fsi->substream = substream;
283 fsi->buffer_len = buffer_len;
284 fsi->period_len = period_len;
285 fsi->byte_offset = 0;
286 fsi->periods = 0;
287}
288
289static void fsi_stream_pop(struct fsi_priv *fsi)
290{
291 fsi->substream = NULL;
292 fsi->buffer_len = 0;
293 fsi->period_len = 0;
294 fsi->byte_offset = 0;
295 fsi->periods = 0;
296}
297
298static int fsi_get_fifo_residue(struct fsi_priv *fsi, int is_play)
299{
300 u32 status;
301 u32 reg = is_play ? DOFF_ST : DIFF_ST;
302 int residue;
303
304 status = fsi_reg_read(fsi, reg);
305 residue = 0x1ff & (status >> 8);
306 residue *= fsi->chan;
307
308 return residue;
309}
310
311static int fsi_get_residue(struct fsi_priv *fsi, int is_play)
312{
313 int residue;
314 int width;
315 struct snd_pcm_runtime *runtime;
316
317 runtime = fsi->substream->runtime;
318
319 /* get 1 channel data width */
320 width = frames_to_bytes(runtime, 1) / fsi->chan;
321
322 if (2 == width)
323 residue = fsi_get_fifo_residue(fsi, is_play);
324 else
325 residue = get_dma_residue(fsi->dma_chan);
326
327 return residue;
328}
329
330/************************************************************************
331
332
333 basic dma function
334
335
336************************************************************************/
337#define PORTA_DMA 0
338#define PORTB_DMA 1
339
340static int fsi_get_dma_chan(void)
341{
342 if (0 != request_dma(PORTA_DMA, "fsia"))
343 return -EIO;
344
345 if (0 != request_dma(PORTB_DMA, "fsib")) {
346 free_dma(PORTA_DMA);
347 return -EIO;
348 }
349
350 master->fsia.dma_chan = PORTA_DMA;
351 master->fsib.dma_chan = PORTB_DMA;
352
353 return 0;
354}
355
356static void fsi_free_dma_chan(void)
357{
358 dma_wait_for_completion(PORTA_DMA);
359 dma_wait_for_completion(PORTB_DMA);
360 free_dma(PORTA_DMA);
361 free_dma(PORTB_DMA);
362
363 master->fsia.dma_chan = -1;
364 master->fsib.dma_chan = -1;
365}
366
367/************************************************************************
368
369
370 ctrl function
371
372
373************************************************************************/
374static void fsi_irq_enable(struct fsi_priv *fsi, int is_play)
375{
376 u32 data = fsi_port_ab_io_bit(fsi, is_play);
377
378 fsi_master_mask_set(IMSK, data, data);
379 fsi_master_mask_set(IEMSK, data, data);
380}
381
382static void fsi_irq_disable(struct fsi_priv *fsi, int is_play)
383{
384 u32 data = fsi_port_ab_io_bit(fsi, is_play);
385
386 fsi_master_mask_set(IMSK, data, 0);
387 fsi_master_mask_set(IEMSK, data, 0);
388}
389
390static void fsi_clk_ctrl(struct fsi_priv *fsi, int enable)
391{
392 u32 val = fsi_is_port_a(fsi) ? (1 << 0) : (1 << 4);
393
394 if (enable)
395 fsi_master_mask_set(CLK_RST, val, val);
396 else
397 fsi_master_mask_set(CLK_RST, val, 0);
398}
399
400static void fsi_irq_init(struct fsi_priv *fsi, int is_play)
401{
402 u32 data;
403 u32 ctrl;
404
405 data = fsi_port_ab_io_bit(fsi, is_play);
406 ctrl = is_play ? DOFF_CTL : DIFF_CTL;
407
408 /* set IMSK */
409 fsi_irq_disable(fsi, is_play);
410
411 /* set interrupt generation factor */
412 fsi_reg_write(fsi, ctrl, IRQ_HALF);
413
414 /* clear FIFO */
415 fsi_reg_mask_set(fsi, ctrl, FIFO_CLR, FIFO_CLR);
416
417 /* clear interrupt factor */
418 fsi_master_mask_set(INT_ST, data, 0);
419}
420
421static void fsi_soft_all_reset(void)
422{
423 u32 status = fsi_master_read(SOFT_RST);
424
425 /* port AB reset */
426 status &= 0x000000ff;
427 fsi_master_write(SOFT_RST, status);
428 mdelay(10);
429
430 /* soft reset */
431 status &= 0x000000f0;
432 fsi_master_write(SOFT_RST, status);
433 status |= 0x00000001;
434 fsi_master_write(SOFT_RST, status);
435 mdelay(10);
436}
437
438static void fsi_16data_push(struct fsi_priv *fsi,
439 struct snd_pcm_runtime *runtime,
440 int send)
441{
442 u16 *dma_start;
443 u32 snd;
444 int i;
445
446 /* get dma start position for FSI */
447 dma_start = (u16 *)runtime->dma_area;
448 dma_start += fsi->byte_offset / 2;
449
450 /*
451 * soft dma
452 * FSI can not use DMA when 16bpp
453 */
454 for (i = 0; i < send; i++) {
455 snd = (u32)dma_start[i];
456 fsi_reg_write(fsi, DODT, snd << 8);
457 }
458}
459
460static void fsi_32data_push(struct fsi_priv *fsi,
461 struct snd_pcm_runtime *runtime,
462 int send)
463{
464 u32 *dma_start;
465
466 /* get dma start position for FSI */
467 dma_start = (u32 *)runtime->dma_area;
468 dma_start += fsi->byte_offset / 4;
469
470 dma_wait_for_completion(fsi->dma_chan);
471 dma_configure_channel(fsi->dma_chan, (SM_INC|0x400|TS_32|TM_BUR));
472 dma_write(fsi->dma_chan, (u32)dma_start,
473 (u32)(fsi->base + DODT), send * 4);
474}
475
476/* playback interrupt */
477static int fsi_data_push(struct fsi_priv *fsi)
478{
479 struct snd_pcm_runtime *runtime;
480 struct snd_pcm_substream *substream = NULL;
481 int send;
482 int fifo_free;
483 int width;
484
485 if (!fsi ||
486 !fsi->substream ||
487 !fsi->substream->runtime)
488 return -EINVAL;
489
490 runtime = fsi->substream->runtime;
491
492 /* FSI FIFO has limit.
493 * So, this driver can not send periods data at a time
494 */
495 if (fsi->byte_offset >=
496 fsi->period_len * (fsi->periods + 1)) {
497
498 substream = fsi->substream;
499 fsi->periods = (fsi->periods + 1) % runtime->periods;
500
501 if (0 == fsi->periods)
502 fsi->byte_offset = 0;
503 }
504
505 /* get 1 channel data width */
506 width = frames_to_bytes(runtime, 1) / fsi->chan;
507
508 /* get send size for alsa */
509 send = (fsi->buffer_len - fsi->byte_offset) / width;
510
511 /* get FIFO free size */
512 fifo_free = (fsi->fifo_max * fsi->chan) - fsi_get_fifo_residue(fsi, 1);
513
514 /* size check */
515 if (fifo_free < send)
516 send = fifo_free;
517
518 if (2 == width)
519 fsi_16data_push(fsi, runtime, send);
520 else if (4 == width)
521 fsi_32data_push(fsi, runtime, send);
522 else
523 return -EINVAL;
524
525 fsi->byte_offset += send * width;
526
527 fsi_irq_enable(fsi, 1);
528
529 if (substream)
530 snd_pcm_period_elapsed(substream);
531
532 return 0;
533}
534
535static irqreturn_t fsi_interrupt(int irq, void *data)
536{
537 u32 status = fsi_master_read(SOFT_RST) & ~0x00000010;
538 u32 int_st = fsi_master_read(INT_ST);
539
540 /* clear irq status */
541 fsi_master_write(SOFT_RST, status);
542 fsi_master_write(SOFT_RST, status | 0x00000010);
543
544 if (int_st & INT_A_OUT)
545 fsi_data_push(&master->fsia);
546 if (int_st & INT_B_OUT)
547 fsi_data_push(&master->fsib);
548
549 fsi_master_write(INT_ST, 0x0000000);
550
551 return IRQ_HANDLED;
552}
553
554/************************************************************************
555
556
557 dai ops
558
559
560************************************************************************/
561static int fsi_dai_startup(struct snd_pcm_substream *substream,
562 struct snd_soc_dai *dai)
563{
564 struct fsi_priv *fsi = fsi_get(substream);
565 const char *msg;
566 u32 flags = fsi_get_info_flags(fsi);
567 u32 fmt;
568 u32 reg;
569 u32 data;
570 int is_play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
571 int is_master;
572 int ret = 0;
573
574 clk_enable(master->clk);
575
576 /* CKG1 */
577 data = is_play ? (1 << 0) : (1 << 4);
578 is_master = fsi_is_master_mode(fsi, is_play);
579 if (is_master)
580 fsi_reg_mask_set(fsi, CKG1, data, data);
581 else
582 fsi_reg_mask_set(fsi, CKG1, data, 0);
583
584 /* clock inversion (CKG2) */
585 data = 0;
586 switch (SH_FSI_INVERSION_MASK & flags) {
587 case SH_FSI_LRM_INV:
588 data = 1 << 12;
589 break;
590 case SH_FSI_BRM_INV:
591 data = 1 << 8;
592 break;
593 case SH_FSI_LRS_INV:
594 data = 1 << 4;
595 break;
596 case SH_FSI_BRS_INV:
597 data = 1 << 0;
598 break;
599 }
600 fsi_reg_write(fsi, CKG2, data);
601
602 /* do fmt, di fmt */
603 data = 0;
604 reg = is_play ? DO_FMT : DI_FMT;
605 fmt = is_play ? SH_FSI_GET_OFMT(flags) : SH_FSI_GET_IFMT(flags);
606 switch (fmt) {
607 case SH_FSI_FMT_MONO:
608 msg = "MONO";
609 data = CR_FMT(CR_MONO);
610 fsi->chan = 1;
611 break;
612 case SH_FSI_FMT_MONO_DELAY:
613 msg = "MONO Delay";
614 data = CR_FMT(CR_MONO_D);
615 fsi->chan = 1;
616 break;
617 case SH_FSI_FMT_PCM:
618 msg = "PCM";
619 data = CR_FMT(CR_PCM);
620 fsi->chan = 2;
621 break;
622 case SH_FSI_FMT_I2S:
623 msg = "I2S";
624 data = CR_FMT(CR_I2S);
625 fsi->chan = 2;
626 break;
627 case SH_FSI_FMT_TDM:
628 msg = "TDM";
629 data = CR_FMT(CR_TDM) | (fsi->chan - 1);
630 fsi->chan = is_play ?
631 SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags);
632 break;
633 case SH_FSI_FMT_TDM_DELAY:
634 msg = "TDM Delay";
635 data = CR_FMT(CR_TDM_D) | (fsi->chan - 1);
636 fsi->chan = is_play ?
637 SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags);
638 break;
639 default:
640 dev_err(dai->dev, "unknown format.\n");
641 return -EINVAL;
642 }
643
644 switch (fsi->chan) {
645 case 1:
646 fsi->fifo_max = 256;
647 break;
648 case 2:
649 fsi->fifo_max = 128;
650 break;
651 case 3:
652 case 4:
653 fsi->fifo_max = 64;
654 break;
655 case 5:
656 case 6:
657 case 7:
658 case 8:
659 fsi->fifo_max = 32;
660 break;
661 default:
662 dev_err(dai->dev, "channel size error.\n");
663 return -EINVAL;
664 }
665
666 fsi_reg_write(fsi, reg, data);
667 dev_dbg(dai->dev, "use %s format (%d channel) use %d DMAC\n",
668 msg, fsi->chan, fsi->dma_chan);
669
670 /*
671 * clear clk reset if master mode
672 */
673 if (is_master)
674 fsi_clk_ctrl(fsi, 1);
675
676 /* irq setting */
677 fsi_irq_init(fsi, is_play);
678
679 return ret;
680}
681
682static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
683 struct snd_soc_dai *dai)
684{
685 struct fsi_priv *fsi = fsi_get(substream);
686 int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
687
688 fsi_irq_disable(fsi, is_play);
689 fsi_clk_ctrl(fsi, 0);
690
691 clk_disable(master->clk);
692}
693
694static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
695 struct snd_soc_dai *dai)
696{
697 struct fsi_priv *fsi = fsi_get(substream);
698 struct snd_pcm_runtime *runtime = substream->runtime;
699 int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
700 int ret = 0;
701
702 /* capture not supported */
703 if (!is_play)
704 return -ENODEV;
705
706 switch (cmd) {
707 case SNDRV_PCM_TRIGGER_START:
708 fsi_stream_push(fsi, substream,
709 frames_to_bytes(runtime, runtime->buffer_size),
710 frames_to_bytes(runtime, runtime->period_size));
711 ret = fsi_data_push(fsi);
712 break;
713 case SNDRV_PCM_TRIGGER_STOP:
714 fsi_irq_disable(fsi, is_play);
715 fsi_stream_pop(fsi);
716 break;
717 }
718
719 return ret;
720}
721
722static struct snd_soc_dai_ops fsi_dai_ops = {
723 .startup = fsi_dai_startup,
724 .shutdown = fsi_dai_shutdown,
725 .trigger = fsi_dai_trigger,
726};
727
728/************************************************************************
729
730
731 pcm ops
732
733
734************************************************************************/
735static struct snd_pcm_hardware fsi_pcm_hardware = {
736 .info = SNDRV_PCM_INFO_INTERLEAVED |
737 SNDRV_PCM_INFO_MMAP |
738 SNDRV_PCM_INFO_MMAP_VALID |
739 SNDRV_PCM_INFO_PAUSE,
740 .formats = FSI_FMTS,
741 .rates = FSI_RATES,
742 .rate_min = 8000,
743 .rate_max = 192000,
744 .channels_min = 1,
745 .channels_max = 2,
746 .buffer_bytes_max = 64 * 1024,
747 .period_bytes_min = 32,
748 .period_bytes_max = 8192,
749 .periods_min = 1,
750 .periods_max = 32,
751 .fifo_size = 256,
752};
753
754static int fsi_pcm_open(struct snd_pcm_substream *substream)
755{
756 struct snd_pcm_runtime *runtime = substream->runtime;
757 int ret = 0;
758
759 snd_soc_set_runtime_hwparams(substream, &fsi_pcm_hardware);
760
761 ret = snd_pcm_hw_constraint_integer(runtime,
762 SNDRV_PCM_HW_PARAM_PERIODS);
763
764 return ret;
765}
766
767static int fsi_hw_params(struct snd_pcm_substream *substream,
768 struct snd_pcm_hw_params *hw_params)
769{
770 return snd_pcm_lib_malloc_pages(substream,
771 params_buffer_bytes(hw_params));
772}
773
774static int fsi_hw_free(struct snd_pcm_substream *substream)
775{
776 return snd_pcm_lib_free_pages(substream);
777}
778
779static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream)
780{
781 struct snd_pcm_runtime *runtime = substream->runtime;
782 struct fsi_priv *fsi = fsi_get(substream);
783 int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
784 long location;
785
786 location = (fsi->byte_offset - 1) - fsi_get_residue(fsi, is_play);
787 if (location < 0)
788 location = 0;
789
790 return bytes_to_frames(runtime, location);
791}
792
793static struct snd_pcm_ops fsi_pcm_ops = {
794 .open = fsi_pcm_open,
795 .ioctl = snd_pcm_lib_ioctl,
796 .hw_params = fsi_hw_params,
797 .hw_free = fsi_hw_free,
798 .pointer = fsi_pointer,
799};
800
801/************************************************************************
802
803
804 snd_soc_platform
805
806
807************************************************************************/
808#define PREALLOC_BUFFER (32 * 1024)
809#define PREALLOC_BUFFER_MAX (32 * 1024)
810
811static void fsi_pcm_free(struct snd_pcm *pcm)
812{
813 snd_pcm_lib_preallocate_free_for_all(pcm);
814}
815
816static int fsi_pcm_new(struct snd_card *card,
817 struct snd_soc_dai *dai,
818 struct snd_pcm *pcm)
819{
820 /*
821 * dont use SNDRV_DMA_TYPE_DEV, since it will oops the SH kernel
822 * in MMAP mode (i.e. aplay -M)
823 */
824 return snd_pcm_lib_preallocate_pages_for_all(
825 pcm,
826 SNDRV_DMA_TYPE_CONTINUOUS,
827 snd_dma_continuous_data(GFP_KERNEL),
828 PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);
829}
830
831/************************************************************************
832
833
834 alsa struct
835
836
837************************************************************************/
838struct snd_soc_dai fsi_soc_dai[] = {
839 {
840 .name = "FSIA",
841 .id = 0,
842 .playback = {
843 .rates = FSI_RATES,
844 .formats = FSI_FMTS,
845 .channels_min = 1,
846 .channels_max = 8,
847 },
848 /* capture not supported */
849 .ops = &fsi_dai_ops,
850 },
851 {
852 .name = "FSIB",
853 .id = 1,
854 .playback = {
855 .rates = FSI_RATES,
856 .formats = FSI_FMTS,
857 .channels_min = 1,
858 .channels_max = 8,
859 },
860 /* capture not supported */
861 .ops = &fsi_dai_ops,
862 },
863};
864EXPORT_SYMBOL_GPL(fsi_soc_dai);
865
866struct snd_soc_platform fsi_soc_platform = {
867 .name = "fsi-pcm",
868 .pcm_ops = &fsi_pcm_ops,
869 .pcm_new = fsi_pcm_new,
870 .pcm_free = fsi_pcm_free,
871};
872EXPORT_SYMBOL_GPL(fsi_soc_platform);
873
874/************************************************************************
875
876
877 platform function
878
879
880************************************************************************/
881static int fsi_probe(struct platform_device *pdev)
882{
883 struct resource *res;
884 char clk_name[8];
885 unsigned int irq;
886 int ret;
887
888 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
889 irq = platform_get_irq(pdev, 0);
890 if (!res || !irq) {
891 dev_err(&pdev->dev, "Not enough FSI platform resources.\n");
892 ret = -ENODEV;
893 goto exit;
894 }
895
896 master = kzalloc(sizeof(*master), GFP_KERNEL);
897 if (!master) {
898 dev_err(&pdev->dev, "Could not allocate master\n");
899 ret = -ENOMEM;
900 goto exit;
901 }
902
903 master->base = ioremap_nocache(res->start, resource_size(res));
904 if (!master->base) {
905 ret = -ENXIO;
906 dev_err(&pdev->dev, "Unable to ioremap FSI registers.\n");
907 goto exit_kfree;
908 }
909
910 master->irq = irq;
911 master->info = pdev->dev.platform_data;
912 master->fsia.base = master->base;
913 master->fsib.base = master->base + 0x40;
914
915 master->fsia.dma_chan = -1;
916 master->fsib.dma_chan = -1;
917
918 ret = fsi_get_dma_chan();
919 if (ret < 0) {
920 dev_err(&pdev->dev, "cannot get dma api\n");
921 goto exit_iounmap;
922 }
923
924 /* FSI is based on SPU mstp */
925 snprintf(clk_name, sizeof(clk_name), "spu%d", pdev->id);
926 master->clk = clk_get(NULL, clk_name);
927 if (IS_ERR(master->clk)) {
928 dev_err(&pdev->dev, "cannot get %s mstp\n", clk_name);
929 ret = -EIO;
930 goto exit_free_dma;
931 }
932
933 fsi_soc_dai[0].dev = &pdev->dev;
934 fsi_soc_dai[1].dev = &pdev->dev;
935
936 fsi_soft_all_reset();
937
938 ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, "fsi", master);
939 if (ret) {
940 dev_err(&pdev->dev, "irq request err\n");
941 goto exit_free_dma;
942 }
943
944 ret = snd_soc_register_platform(&fsi_soc_platform);
945 if (ret < 0) {
946 dev_err(&pdev->dev, "cannot snd soc register\n");
947 goto exit_free_irq;
948 }
949
950 return snd_soc_register_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai));
951
952exit_free_irq:
953 free_irq(irq, master);
954exit_free_dma:
955 fsi_free_dma_chan();
956exit_iounmap:
957 iounmap(master->base);
958exit_kfree:
959 kfree(master);
960 master = NULL;
961exit:
962 return ret;
963}
964
965static int fsi_remove(struct platform_device *pdev)
966{
967 snd_soc_unregister_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai));
968 snd_soc_unregister_platform(&fsi_soc_platform);
969
970 clk_put(master->clk);
971
972 fsi_free_dma_chan();
973
974 free_irq(master->irq, master);
975
976 iounmap(master->base);
977 kfree(master);
978 master = NULL;
979 return 0;
980}
981
982static struct platform_driver fsi_driver = {
983 .driver = {
984 .name = "sh_fsi",
985 },
986 .probe = fsi_probe,
987 .remove = fsi_remove,
988};
989
990static int __init fsi_mobile_init(void)
991{
992 return platform_driver_register(&fsi_driver);
993}
994
995static void __exit fsi_mobile_exit(void)
996{
997 platform_driver_unregister(&fsi_driver);
998}
999module_init(fsi_mobile_init);
1000module_exit(fsi_mobile_exit);
1001
1002MODULE_LICENSE("GPL");
1003MODULE_DESCRIPTION("SuperH onchip FSI audio driver");
1004MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>");
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
index c8ceddc2a26c..d2505e8b06c9 100644
--- a/sound/soc/soc-cache.c
+++ b/sound/soc/soc-cache.c
@@ -77,6 +77,35 @@ static int snd_soc_7_9_spi_write(void *control_data, const char *data,
77#define snd_soc_7_9_spi_write NULL 77#define snd_soc_7_9_spi_write NULL
78#endif 78#endif
79 79
80static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg,
81 unsigned int value)
82{
83 u8 *cache = codec->reg_cache;
84 u8 data[2];
85
86 BUG_ON(codec->volatile_register);
87
88 data[0] = reg & 0xff;
89 data[1] = value & 0xff;
90
91 if (reg < codec->reg_cache_size)
92 cache[reg] = value;
93
94 if (codec->hw_write(codec->control_data, data, 2) == 2)
95 return 0;
96 else
97 return -EIO;
98}
99
100static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec,
101 unsigned int reg)
102{
103 u8 *cache = codec->reg_cache;
104 if (reg >= codec->reg_cache_size)
105 return -1;
106 return cache[reg];
107}
108
80static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg, 109static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
81 unsigned int value) 110 unsigned int value)
82{ 111{
@@ -150,9 +179,20 @@ static struct {
150 unsigned int (*read)(struct snd_soc_codec *, unsigned int); 179 unsigned int (*read)(struct snd_soc_codec *, unsigned int);
151 unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int); 180 unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int);
152} io_types[] = { 181} io_types[] = {
153 { 7, 9, snd_soc_7_9_write, snd_soc_7_9_spi_write, snd_soc_7_9_read }, 182 {
154 { 8, 16, snd_soc_8_16_write, NULL, snd_soc_8_16_read, 183 .addr_bits = 7, .data_bits = 9,
155 snd_soc_8_16_read_i2c }, 184 .write = snd_soc_7_9_write, .read = snd_soc_7_9_read,
185 .spi_write = snd_soc_7_9_spi_write
186 },
187 {
188 .addr_bits = 8, .data_bits = 8,
189 .write = snd_soc_8_8_write, .read = snd_soc_8_8_read,
190 },
191 {
192 .addr_bits = 8, .data_bits = 16,
193 .write = snd_soc_8_16_write, .read = snd_soc_8_16_read,
194 .i2c_read = snd_soc_8_16_read_i2c,
195 },
156}; 196};
157 197
158/** 198/**
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index e984a17cd656..f5b356f8acfb 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1267,10 +1267,18 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
1267 if (!codec->debugfs_pop_time) 1267 if (!codec->debugfs_pop_time)
1268 printk(KERN_WARNING 1268 printk(KERN_WARNING
1269 "Failed to create pop time debugfs file\n"); 1269 "Failed to create pop time debugfs file\n");
1270
1271 codec->debugfs_dapm = debugfs_create_dir("dapm", debugfs_root);
1272 if (!codec->debugfs_dapm)
1273 printk(KERN_WARNING
1274 "Failed to create DAPM debugfs directory\n");
1275
1276 snd_soc_dapm_debugfs_init(codec);
1270} 1277}
1271 1278
1272static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec) 1279static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
1273{ 1280{
1281 debugfs_remove_recursive(codec->debugfs_dapm);
1274 debugfs_remove(codec->debugfs_pop_time); 1282 debugfs_remove(codec->debugfs_pop_time);
1275 debugfs_remove(codec->debugfs_reg); 1283 debugfs_remove(codec->debugfs_reg);
1276} 1284}
@@ -2189,16 +2197,18 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv);
2189 * snd_soc_dai_set_pll - configure DAI PLL. 2197 * snd_soc_dai_set_pll - configure DAI PLL.
2190 * @dai: DAI 2198 * @dai: DAI
2191 * @pll_id: DAI specific PLL ID 2199 * @pll_id: DAI specific PLL ID
2200 * @source: DAI specific source for the PLL
2192 * @freq_in: PLL input clock frequency in Hz 2201 * @freq_in: PLL input clock frequency in Hz
2193 * @freq_out: requested PLL output clock frequency in Hz 2202 * @freq_out: requested PLL output clock frequency in Hz
2194 * 2203 *
2195 * Configures and enables PLL to generate output clock based on input clock. 2204 * Configures and enables PLL to generate output clock based on input clock.
2196 */ 2205 */
2197int snd_soc_dai_set_pll(struct snd_soc_dai *dai, 2206int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
2198 int pll_id, unsigned int freq_in, unsigned int freq_out) 2207 unsigned int freq_in, unsigned int freq_out)
2199{ 2208{
2200 if (dai->ops && dai->ops->set_pll) 2209 if (dai->ops && dai->ops->set_pll)
2201 return dai->ops->set_pll(dai, pll_id, freq_in, freq_out); 2210 return dai->ops->set_pll(dai, pll_id, source,
2211 freq_in, freq_out);
2202 else 2212 else
2203 return -EINVAL; 2213 return -EINVAL;
2204} 2214}
@@ -2243,6 +2253,30 @@ int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
2243EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); 2253EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);
2244 2254
2245/** 2255/**
2256 * snd_soc_dai_set_channel_map - configure DAI audio channel map
2257 * @dai: DAI
2258 * @tx_num: how many TX channels
2259 * @tx_slot: pointer to an array which imply the TX slot number channel
2260 * 0~num-1 uses
2261 * @rx_num: how many RX channels
2262 * @rx_slot: pointer to an array which imply the RX slot number channel
2263 * 0~num-1 uses
2264 *
2265 * configure the relationship between channel number and TDM slot number.
2266 */
2267int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai,
2268 unsigned int tx_num, unsigned int *tx_slot,
2269 unsigned int rx_num, unsigned int *rx_slot)
2270{
2271 if (dai->ops && dai->ops->set_channel_map)
2272 return dai->ops->set_channel_map(dai, tx_num, tx_slot,
2273 rx_num, rx_slot);
2274 else
2275 return -EINVAL;
2276}
2277EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map);
2278
2279/**
2246 * snd_soc_dai_set_tristate - configure DAI system or master clock. 2280 * snd_soc_dai_set_tristate - configure DAI system or master clock.
2247 * @dai: DAI 2281 * @dai: DAI
2248 * @tristate: tristate enable 2282 * @tristate: tristate enable
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 88461310dc96..9babda559c92 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -37,6 +37,7 @@
37#include <linux/bitops.h> 37#include <linux/bitops.h>
38#include <linux/platform_device.h> 38#include <linux/platform_device.h>
39#include <linux/jiffies.h> 39#include <linux/jiffies.h>
40#include <linux/debugfs.h>
40#include <sound/core.h> 41#include <sound/core.h>
41#include <sound/pcm.h> 42#include <sound/pcm.h>
42#include <sound/pcm_params.h> 43#include <sound/pcm_params.h>
@@ -55,17 +56,19 @@ static int dapm_up_seq[] = {
55 [snd_soc_dapm_pre] = 0, 56 [snd_soc_dapm_pre] = 0,
56 [snd_soc_dapm_supply] = 1, 57 [snd_soc_dapm_supply] = 1,
57 [snd_soc_dapm_micbias] = 2, 58 [snd_soc_dapm_micbias] = 2,
58 [snd_soc_dapm_mic] = 3, 59 [snd_soc_dapm_aif_in] = 3,
59 [snd_soc_dapm_mux] = 4, 60 [snd_soc_dapm_aif_out] = 3,
60 [snd_soc_dapm_value_mux] = 4, 61 [snd_soc_dapm_mic] = 4,
61 [snd_soc_dapm_dac] = 5, 62 [snd_soc_dapm_mux] = 5,
62 [snd_soc_dapm_mixer] = 6, 63 [snd_soc_dapm_value_mux] = 5,
63 [snd_soc_dapm_mixer_named_ctl] = 6, 64 [snd_soc_dapm_dac] = 6,
64 [snd_soc_dapm_pga] = 7, 65 [snd_soc_dapm_mixer] = 7,
65 [snd_soc_dapm_adc] = 8, 66 [snd_soc_dapm_mixer_named_ctl] = 7,
66 [snd_soc_dapm_hp] = 9, 67 [snd_soc_dapm_pga] = 8,
67 [snd_soc_dapm_spk] = 9, 68 [snd_soc_dapm_adc] = 9,
68 [snd_soc_dapm_post] = 10, 69 [snd_soc_dapm_hp] = 10,
70 [snd_soc_dapm_spk] = 10,
71 [snd_soc_dapm_post] = 11,
69}; 72};
70 73
71static int dapm_down_seq[] = { 74static int dapm_down_seq[] = {
@@ -81,8 +84,10 @@ static int dapm_down_seq[] = {
81 [snd_soc_dapm_micbias] = 8, 84 [snd_soc_dapm_micbias] = 8,
82 [snd_soc_dapm_mux] = 9, 85 [snd_soc_dapm_mux] = 9,
83 [snd_soc_dapm_value_mux] = 9, 86 [snd_soc_dapm_value_mux] = 9,
84 [snd_soc_dapm_supply] = 10, 87 [snd_soc_dapm_aif_in] = 10,
85 [snd_soc_dapm_post] = 11, 88 [snd_soc_dapm_aif_out] = 10,
89 [snd_soc_dapm_supply] = 11,
90 [snd_soc_dapm_post] = 12,
86}; 91};
87 92
88static void pop_wait(u32 pop_time) 93static void pop_wait(u32 pop_time)
@@ -148,8 +153,12 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev,
148 153
149 if (card->set_bias_level) 154 if (card->set_bias_level)
150 ret = card->set_bias_level(card, level); 155 ret = card->set_bias_level(card, level);
151 if (ret == 0 && codec->set_bias_level) 156 if (ret == 0) {
152 ret = codec->set_bias_level(codec, level); 157 if (codec->set_bias_level)
158 ret = codec->set_bias_level(codec, level);
159 else
160 codec->bias_level = level;
161 }
153 162
154 return ret; 163 return ret;
155} 164}
@@ -224,6 +233,8 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
224 case snd_soc_dapm_micbias: 233 case snd_soc_dapm_micbias:
225 case snd_soc_dapm_vmid: 234 case snd_soc_dapm_vmid:
226 case snd_soc_dapm_supply: 235 case snd_soc_dapm_supply:
236 case snd_soc_dapm_aif_in:
237 case snd_soc_dapm_aif_out:
227 p->connect = 1; 238 p->connect = 1;
228 break; 239 break;
229 /* does effect routing - dynamically connected */ 240 /* does effect routing - dynamically connected */
@@ -497,8 +508,14 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
497 if (widget->id == snd_soc_dapm_supply) 508 if (widget->id == snd_soc_dapm_supply)
498 return 0; 509 return 0;
499 510
500 if (widget->id == snd_soc_dapm_adc && widget->active) 511 switch (widget->id) {
501 return 1; 512 case snd_soc_dapm_adc:
513 case snd_soc_dapm_aif_out:
514 if (widget->active)
515 return 1;
516 default:
517 break;
518 }
502 519
503 if (widget->connected) { 520 if (widget->connected) {
504 /* connected pin ? */ 521 /* connected pin ? */
@@ -537,8 +554,14 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
537 return 0; 554 return 0;
538 555
539 /* active stream ? */ 556 /* active stream ? */
540 if (widget->id == snd_soc_dapm_dac && widget->active) 557 switch (widget->id) {
541 return 1; 558 case snd_soc_dapm_dac:
559 case snd_soc_dapm_aif_in:
560 if (widget->active)
561 return 1;
562 default:
563 break;
564 }
542 565
543 if (widget->connected) { 566 if (widget->connected) {
544 /* connected pin ? */ 567 /* connected pin ? */
@@ -695,6 +718,10 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
695 718
696 /* Check if one of our outputs is connected */ 719 /* Check if one of our outputs is connected */
697 list_for_each_entry(path, &w->sinks, list_source) { 720 list_for_each_entry(path, &w->sinks, list_source) {
721 if (path->connected &&
722 !path->connected(path->source, path->sink))
723 continue;
724
698 if (path->sink && path->sink->power_check && 725 if (path->sink && path->sink->power_check &&
699 path->sink->power_check(path->sink)) { 726 path->sink->power_check(path->sink)) {
700 power = 1; 727 power = 1;
@@ -1052,6 +1079,8 @@ static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action)
1052 case snd_soc_dapm_mixer: 1079 case snd_soc_dapm_mixer:
1053 case snd_soc_dapm_mixer_named_ctl: 1080 case snd_soc_dapm_mixer_named_ctl:
1054 case snd_soc_dapm_supply: 1081 case snd_soc_dapm_supply:
1082 case snd_soc_dapm_aif_in:
1083 case snd_soc_dapm_aif_out:
1055 if (w->name) { 1084 if (w->name) {
1056 in = is_connected_input_ep(w); 1085 in = is_connected_input_ep(w);
1057 dapm_clear_walk(w->codec); 1086 dapm_clear_walk(w->codec);
@@ -1077,6 +1106,99 @@ static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action)
1077} 1106}
1078#endif 1107#endif
1079 1108
1109#ifdef CONFIG_DEBUG_FS
1110static int dapm_widget_power_open_file(struct inode *inode, struct file *file)
1111{
1112 file->private_data = inode->i_private;
1113 return 0;
1114}
1115
1116static ssize_t dapm_widget_power_read_file(struct file *file,
1117 char __user *user_buf,
1118 size_t count, loff_t *ppos)
1119{
1120 struct snd_soc_dapm_widget *w = file->private_data;
1121 char *buf;
1122 int in, out;
1123 ssize_t ret;
1124 struct snd_soc_dapm_path *p = NULL;
1125
1126 buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
1127 if (!buf)
1128 return -ENOMEM;
1129
1130 in = is_connected_input_ep(w);
1131 dapm_clear_walk(w->codec);
1132 out = is_connected_output_ep(w);
1133 dapm_clear_walk(w->codec);
1134
1135 ret = snprintf(buf, PAGE_SIZE, "%s: %s in %d out %d\n",
1136 w->name, w->power ? "On" : "Off", in, out);
1137
1138 if (w->sname)
1139 ret += snprintf(buf + ret, PAGE_SIZE - ret, " stream %s %s\n",
1140 w->sname,
1141 w->active ? "active" : "inactive");
1142
1143 list_for_each_entry(p, &w->sources, list_sink) {
1144 if (p->connected && !p->connected(w, p->sink))
1145 continue;
1146
1147 if (p->connect)
1148 ret += snprintf(buf + ret, PAGE_SIZE - ret,
1149 " in %s %s\n",
1150 p->name ? p->name : "static",
1151 p->source->name);
1152 }
1153 list_for_each_entry(p, &w->sinks, list_source) {
1154 if (p->connected && !p->connected(w, p->sink))
1155 continue;
1156
1157 if (p->connect)
1158 ret += snprintf(buf + ret, PAGE_SIZE - ret,
1159 " out %s %s\n",
1160 p->name ? p->name : "static",
1161 p->sink->name);
1162 }
1163
1164 ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
1165
1166 kfree(buf);
1167 return ret;
1168}
1169
1170static const struct file_operations dapm_widget_power_fops = {
1171 .open = dapm_widget_power_open_file,
1172 .read = dapm_widget_power_read_file,
1173};
1174
1175void snd_soc_dapm_debugfs_init(struct snd_soc_codec *codec)
1176{
1177 struct snd_soc_dapm_widget *w;
1178 struct dentry *d;
1179
1180 if (!codec->debugfs_dapm)
1181 return;
1182
1183 list_for_each_entry(w, &codec->dapm_widgets, list) {
1184 if (!w->name)
1185 continue;
1186
1187 d = debugfs_create_file(w->name, 0444,
1188 codec->debugfs_dapm, w,
1189 &dapm_widget_power_fops);
1190 if (!d)
1191 printk(KERN_WARNING
1192 "ASoC: Failed to create %s debugfs file\n",
1193 w->name);
1194 }
1195}
1196#else
1197void snd_soc_dapm_debugfs_init(struct snd_soc_codec *codec)
1198{
1199}
1200#endif
1201
1080/* test and update the power status of a mux widget */ 1202/* test and update the power status of a mux widget */
1081static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget, 1203static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
1082 struct snd_kcontrol *kcontrol, int mask, 1204 struct snd_kcontrol *kcontrol, int mask,
@@ -1274,10 +1396,13 @@ int snd_soc_dapm_sync(struct snd_soc_codec *codec)
1274EXPORT_SYMBOL_GPL(snd_soc_dapm_sync); 1396EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
1275 1397
1276static int snd_soc_dapm_add_route(struct snd_soc_codec *codec, 1398static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
1277 const char *sink, const char *control, const char *source) 1399 const struct snd_soc_dapm_route *route)
1278{ 1400{
1279 struct snd_soc_dapm_path *path; 1401 struct snd_soc_dapm_path *path;
1280 struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w; 1402 struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
1403 const char *sink = route->sink;
1404 const char *control = route->control;
1405 const char *source = route->source;
1281 int ret = 0; 1406 int ret = 0;
1282 1407
1283 /* find src and dest widgets */ 1408 /* find src and dest widgets */
@@ -1301,6 +1426,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
1301 1426
1302 path->source = wsource; 1427 path->source = wsource;
1303 path->sink = wsink; 1428 path->sink = wsink;
1429 path->connected = route->connected;
1304 INIT_LIST_HEAD(&path->list); 1430 INIT_LIST_HEAD(&path->list);
1305 INIT_LIST_HEAD(&path->list_source); 1431 INIT_LIST_HEAD(&path->list_source);
1306 INIT_LIST_HEAD(&path->list_sink); 1432 INIT_LIST_HEAD(&path->list_sink);
@@ -1342,6 +1468,8 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
1342 case snd_soc_dapm_pre: 1468 case snd_soc_dapm_pre:
1343 case snd_soc_dapm_post: 1469 case snd_soc_dapm_post:
1344 case snd_soc_dapm_supply: 1470 case snd_soc_dapm_supply:
1471 case snd_soc_dapm_aif_in:
1472 case snd_soc_dapm_aif_out:
1345 list_add(&path->list, &codec->dapm_paths); 1473 list_add(&path->list, &codec->dapm_paths);
1346 list_add(&path->list_sink, &wsink->sources); 1474 list_add(&path->list_sink, &wsink->sources);
1347 list_add(&path->list_source, &wsource->sinks); 1475 list_add(&path->list_source, &wsource->sinks);
@@ -1399,8 +1527,7 @@ int snd_soc_dapm_add_routes(struct snd_soc_codec *codec,
1399 int i, ret; 1527 int i, ret;
1400 1528
1401 for (i = 0; i < num; i++) { 1529 for (i = 0; i < num; i++) {
1402 ret = snd_soc_dapm_add_route(codec, route->sink, 1530 ret = snd_soc_dapm_add_route(codec, route);
1403 route->control, route->source);
1404 if (ret < 0) { 1531 if (ret < 0) {
1405 printk(KERN_ERR "Failed to add route %s->%s\n", 1532 printk(KERN_ERR "Failed to add route %s->%s\n",
1406 route->source, 1533 route->source,
@@ -1444,9 +1571,11 @@ int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec)
1444 dapm_new_mux(codec, w); 1571 dapm_new_mux(codec, w);
1445 break; 1572 break;
1446 case snd_soc_dapm_adc: 1573 case snd_soc_dapm_adc:
1574 case snd_soc_dapm_aif_out:
1447 w->power_check = dapm_adc_check_power; 1575 w->power_check = dapm_adc_check_power;
1448 break; 1576 break;
1449 case snd_soc_dapm_dac: 1577 case snd_soc_dapm_dac:
1578 case snd_soc_dapm_aif_in:
1450 w->power_check = dapm_dac_check_power; 1579 w->power_check = dapm_dac_check_power;
1451 break; 1580 break;
1452 case snd_soc_dapm_pga: 1581 case snd_soc_dapm_pga: