aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/pxa/pxa2xx-i2s.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/pxa/pxa2xx-i2s.c')
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c46
1 files changed, 29 insertions, 17 deletions
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index 2f4b6e489b78..6b8f655d1ad8 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -106,10 +106,8 @@ static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream,
106 if (IS_ERR(clk_i2s)) 106 if (IS_ERR(clk_i2s))
107 return PTR_ERR(clk_i2s); 107 return PTR_ERR(clk_i2s);
108 108
109 if (!cpu_dai->active) { 109 if (!cpu_dai->active)
110 SACR0 |= SACR0_RST;
111 SACR0 = 0; 110 SACR0 = 0;
112 }
113 111
114 return 0; 112 return 0;
115} 113}
@@ -169,6 +167,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
169 167
170 BUG_ON(IS_ERR(clk_i2s)); 168 BUG_ON(IS_ERR(clk_i2s));
171 clk_enable(clk_i2s); 169 clk_enable(clk_i2s);
170 dai->private_data = dai;
172 pxa_i2s_wait(); 171 pxa_i2s_wait();
173 172
174 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 173 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -178,9 +177,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
178 177
179 /* is port used by another stream */ 178 /* is port used by another stream */
180 if (!(SACR0 & SACR0_ENB)) { 179 if (!(SACR0 & SACR0_ENB)) {
181
182 SACR0 = 0; 180 SACR0 = 0;
183 SACR1 = 0;
184 if (pxa_i2s.master) 181 if (pxa_i2s.master)
185 SACR0 |= SACR0_BCKD; 182 SACR0 |= SACR0_BCKD;
186 183
@@ -226,6 +223,10 @@ static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
226 223
227 switch (cmd) { 224 switch (cmd) {
228 case SNDRV_PCM_TRIGGER_START: 225 case SNDRV_PCM_TRIGGER_START:
226 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
227 SACR1 &= ~SACR1_DRPL;
228 else
229 SACR1 &= ~SACR1_DREC;
229 SACR0 |= SACR0_ENB; 230 SACR0 |= SACR0_ENB;
230 break; 231 break;
231 case SNDRV_PCM_TRIGGER_RESUME: 232 case SNDRV_PCM_TRIGGER_RESUME:
@@ -252,21 +253,19 @@ static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream,
252 SAIMR &= ~SAIMR_RFS; 253 SAIMR &= ~SAIMR_RFS;
253 } 254 }
254 255
255 if (SACR1 & (SACR1_DREC | SACR1_DRPL)) { 256 if ((SACR1 & (SACR1_DREC | SACR1_DRPL)) == (SACR1_DREC | SACR1_DRPL)) {
256 SACR0 &= ~SACR0_ENB; 257 SACR0 &= ~SACR0_ENB;
257 pxa_i2s_wait(); 258 pxa_i2s_wait();
258 clk_disable(clk_i2s); 259 if (dai->private_data != NULL) {
260 clk_disable(clk_i2s);
261 dai->private_data = NULL;
262 }
259 } 263 }
260
261 clk_put(clk_i2s);
262} 264}
263 265
264#ifdef CONFIG_PM 266#ifdef CONFIG_PM
265static int pxa2xx_i2s_suspend(struct snd_soc_dai *dai) 267static int pxa2xx_i2s_suspend(struct snd_soc_dai *dai)
266{ 268{
267 if (!dai->active)
268 return 0;
269
270 /* store registers */ 269 /* store registers */
271 pxa_i2s.sacr0 = SACR0; 270 pxa_i2s.sacr0 = SACR0;
272 pxa_i2s.sacr1 = SACR1; 271 pxa_i2s.sacr1 = SACR1;
@@ -281,16 +280,14 @@ static int pxa2xx_i2s_suspend(struct snd_soc_dai *dai)
281 280
282static int pxa2xx_i2s_resume(struct snd_soc_dai *dai) 281static int pxa2xx_i2s_resume(struct snd_soc_dai *dai)
283{ 282{
284 if (!dai->active)
285 return 0;
286
287 pxa_i2s_wait(); 283 pxa_i2s_wait();
288 284
289 SACR0 = pxa_i2s.sacr0 &= ~SACR0_ENB; 285 SACR0 = pxa_i2s.sacr0 & ~SACR0_ENB;
290 SACR1 = pxa_i2s.sacr1; 286 SACR1 = pxa_i2s.sacr1;
291 SAIMR = pxa_i2s.saimr; 287 SAIMR = pxa_i2s.saimr;
292 SADIV = pxa_i2s.sadiv; 288 SADIV = pxa_i2s.sadiv;
293 SACR0 |= SACR0_ENB; 289
290 SACR0 = pxa_i2s.sacr0;
294 291
295 return 0; 292 return 0;
296} 293}
@@ -329,6 +326,7 @@ struct snd_soc_dai pxa_i2s_dai = {
329 .rates = PXA2XX_I2S_RATES, 326 .rates = PXA2XX_I2S_RATES,
330 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 327 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
331 .ops = &pxa_i2s_dai_ops, 328 .ops = &pxa_i2s_dai_ops,
329 .symmetric_rates = 1,
332}; 330};
333 331
334EXPORT_SYMBOL_GPL(pxa_i2s_dai); 332EXPORT_SYMBOL_GPL(pxa_i2s_dai);
@@ -342,10 +340,24 @@ static int pxa2xx_i2s_probe(struct platform_device *dev)
342 return PTR_ERR(clk_i2s); 340 return PTR_ERR(clk_i2s);
343 341
344 pxa_i2s_dai.dev = &dev->dev; 342 pxa_i2s_dai.dev = &dev->dev;
343 pxa_i2s_dai.private_data = NULL;
345 ret = snd_soc_register_dai(&pxa_i2s_dai); 344 ret = snd_soc_register_dai(&pxa_i2s_dai);
346 if (ret != 0) 345 if (ret != 0)
347 clk_put(clk_i2s); 346 clk_put(clk_i2s);
348 347
348 /*
349 * PXA Developer's Manual:
350 * If SACR0[ENB] is toggled in the middle of a normal operation,
351 * the SACR0[RST] bit must also be set and cleared to reset all
352 * I2S controller registers.
353 */
354 SACR0 = SACR0_RST;
355 SACR0 = 0;
356 /* Make sure RPL and REC are disabled */
357 SACR1 = SACR1_DRPL | SACR1_DREC;
358 /* Along with FIFO servicing */
359 SAIMR &= ~(SAIMR_RFS | SAIMR_TFS);
360
349 return ret; 361 return ret;
350} 362}
351 363