diff options
Diffstat (limited to 'sound/arm/aaci.c')
-rw-r--r-- | sound/arm/aaci.c | 207 |
1 files changed, 68 insertions, 139 deletions
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c index 1f0f8213e2d5..656e474dca47 100644 --- a/sound/arm/aaci.c +++ b/sound/arm/aaci.c | |||
@@ -18,10 +18,7 @@ | |||
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/err.h> | 19 | #include <linux/err.h> |
20 | #include <linux/amba/bus.h> | 20 | #include <linux/amba/bus.h> |
21 | 21 | #include <linux/io.h> | |
22 | #include <asm/io.h> | ||
23 | #include <asm/irq.h> | ||
24 | #include <asm/sizes.h> | ||
25 | 22 | ||
26 | #include <sound/core.h> | 23 | #include <sound/core.h> |
27 | #include <sound/initval.h> | 24 | #include <sound/initval.h> |
@@ -30,7 +27,6 @@ | |||
30 | #include <sound/pcm_params.h> | 27 | #include <sound/pcm_params.h> |
31 | 28 | ||
32 | #include "aaci.h" | 29 | #include "aaci.h" |
33 | #include "devdma.h" | ||
34 | 30 | ||
35 | #define DRIVER_NAME "aaci-pl041" | 31 | #define DRIVER_NAME "aaci-pl041" |
36 | 32 | ||
@@ -176,14 +172,15 @@ static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg) | |||
176 | return v; | 172 | return v; |
177 | } | 173 | } |
178 | 174 | ||
179 | static inline void aaci_chan_wait_ready(struct aaci_runtime *aacirun) | 175 | static inline void |
176 | aaci_chan_wait_ready(struct aaci_runtime *aacirun, unsigned long mask) | ||
180 | { | 177 | { |
181 | u32 val; | 178 | u32 val; |
182 | int timeout = 5000; | 179 | int timeout = 5000; |
183 | 180 | ||
184 | do { | 181 | do { |
185 | val = readl(aacirun->base + AACI_SR); | 182 | val = readl(aacirun->base + AACI_SR); |
186 | } while (val & (SR_TXB|SR_RXB) && timeout--); | 183 | } while (val & mask && timeout--); |
187 | } | 184 | } |
188 | 185 | ||
189 | 186 | ||
@@ -212,8 +209,10 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) | |||
212 | writel(0, aacirun->base + AACI_IE); | 209 | writel(0, aacirun->base + AACI_IE); |
213 | return; | 210 | return; |
214 | } | 211 | } |
215 | ptr = aacirun->ptr; | ||
216 | 212 | ||
213 | spin_lock(&aacirun->lock); | ||
214 | |||
215 | ptr = aacirun->ptr; | ||
217 | do { | 216 | do { |
218 | unsigned int len = aacirun->fifosz; | 217 | unsigned int len = aacirun->fifosz; |
219 | u32 val; | 218 | u32 val; |
@@ -221,9 +220,9 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) | |||
221 | if (aacirun->bytes <= 0) { | 220 | if (aacirun->bytes <= 0) { |
222 | aacirun->bytes += aacirun->period; | 221 | aacirun->bytes += aacirun->period; |
223 | aacirun->ptr = ptr; | 222 | aacirun->ptr = ptr; |
224 | spin_unlock(&aaci->lock); | 223 | spin_unlock(&aacirun->lock); |
225 | snd_pcm_period_elapsed(aacirun->substream); | 224 | snd_pcm_period_elapsed(aacirun->substream); |
226 | spin_lock(&aaci->lock); | 225 | spin_lock(&aacirun->lock); |
227 | } | 226 | } |
228 | if (!(aacirun->cr & CR_EN)) | 227 | if (!(aacirun->cr & CR_EN)) |
229 | break; | 228 | break; |
@@ -249,7 +248,10 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) | |||
249 | ptr = aacirun->start; | 248 | ptr = aacirun->start; |
250 | } | 249 | } |
251 | } while(1); | 250 | } while(1); |
251 | |||
252 | aacirun->ptr = ptr; | 252 | aacirun->ptr = ptr; |
253 | |||
254 | spin_unlock(&aacirun->lock); | ||
253 | } | 255 | } |
254 | 256 | ||
255 | if (mask & ISR_URINTR) { | 257 | if (mask & ISR_URINTR) { |
@@ -267,6 +269,8 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) | |||
267 | return; | 269 | return; |
268 | } | 270 | } |
269 | 271 | ||
272 | spin_lock(&aacirun->lock); | ||
273 | |||
270 | ptr = aacirun->ptr; | 274 | ptr = aacirun->ptr; |
271 | do { | 275 | do { |
272 | unsigned int len = aacirun->fifosz; | 276 | unsigned int len = aacirun->fifosz; |
@@ -275,9 +279,9 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) | |||
275 | if (aacirun->bytes <= 0) { | 279 | if (aacirun->bytes <= 0) { |
276 | aacirun->bytes += aacirun->period; | 280 | aacirun->bytes += aacirun->period; |
277 | aacirun->ptr = ptr; | 281 | aacirun->ptr = ptr; |
278 | spin_unlock(&aaci->lock); | 282 | spin_unlock(&aacirun->lock); |
279 | snd_pcm_period_elapsed(aacirun->substream); | 283 | snd_pcm_period_elapsed(aacirun->substream); |
280 | spin_lock(&aaci->lock); | 284 | spin_lock(&aacirun->lock); |
281 | } | 285 | } |
282 | if (!(aacirun->cr & CR_EN)) | 286 | if (!(aacirun->cr & CR_EN)) |
283 | break; | 287 | break; |
@@ -305,6 +309,8 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) | |||
305 | } while (1); | 309 | } while (1); |
306 | 310 | ||
307 | aacirun->ptr = ptr; | 311 | aacirun->ptr = ptr; |
312 | |||
313 | spin_unlock(&aacirun->lock); | ||
308 | } | 314 | } |
309 | } | 315 | } |
310 | 316 | ||
@@ -314,7 +320,6 @@ static irqreturn_t aaci_irq(int irq, void *devid) | |||
314 | u32 mask; | 320 | u32 mask; |
315 | int i; | 321 | int i; |
316 | 322 | ||
317 | spin_lock(&aaci->lock); | ||
318 | mask = readl(aaci->base + AACI_ALLINTS); | 323 | mask = readl(aaci->base + AACI_ALLINTS); |
319 | if (mask) { | 324 | if (mask) { |
320 | u32 m = mask; | 325 | u32 m = mask; |
@@ -324,7 +329,6 @@ static irqreturn_t aaci_irq(int irq, void *devid) | |||
324 | } | 329 | } |
325 | } | 330 | } |
326 | } | 331 | } |
327 | spin_unlock(&aaci->lock); | ||
328 | 332 | ||
329 | return mask ? IRQ_HANDLED : IRQ_NONE; | 333 | return mask ? IRQ_HANDLED : IRQ_NONE; |
330 | } | 334 | } |
@@ -334,63 +338,6 @@ static irqreturn_t aaci_irq(int irq, void *devid) | |||
334 | /* | 338 | /* |
335 | * ALSA support. | 339 | * ALSA support. |
336 | */ | 340 | */ |
337 | |||
338 | struct aaci_stream { | ||
339 | unsigned char codec_idx; | ||
340 | unsigned char rate_idx; | ||
341 | }; | ||
342 | |||
343 | static struct aaci_stream aaci_streams[] = { | ||
344 | [ACSTREAM_FRONT] = { | ||
345 | .codec_idx = 0, | ||
346 | .rate_idx = AC97_RATES_FRONT_DAC, | ||
347 | }, | ||
348 | [ACSTREAM_SURROUND] = { | ||
349 | .codec_idx = 0, | ||
350 | .rate_idx = AC97_RATES_SURR_DAC, | ||
351 | }, | ||
352 | [ACSTREAM_LFE] = { | ||
353 | .codec_idx = 0, | ||
354 | .rate_idx = AC97_RATES_LFE_DAC, | ||
355 | }, | ||
356 | }; | ||
357 | |||
358 | static inline unsigned int aaci_rate_mask(struct aaci *aaci, int streamid) | ||
359 | { | ||
360 | struct aaci_stream *s = aaci_streams + streamid; | ||
361 | return aaci->ac97_bus->codec[s->codec_idx]->rates[s->rate_idx]; | ||
362 | } | ||
363 | |||
364 | static unsigned int rate_list[] = { | ||
365 | 5512, 8000, 11025, 16000, 22050, 32000, 44100, | ||
366 | 48000, 64000, 88200, 96000, 176400, 192000 | ||
367 | }; | ||
368 | |||
369 | /* | ||
370 | * Double-rate rule: we can support double rate iff channels == 2 | ||
371 | * (unimplemented) | ||
372 | */ | ||
373 | static int | ||
374 | aaci_rule_rate_by_channels(struct snd_pcm_hw_params *p, struct snd_pcm_hw_rule *rule) | ||
375 | { | ||
376 | struct aaci *aaci = rule->private; | ||
377 | unsigned int rate_mask = SNDRV_PCM_RATE_8000_48000|SNDRV_PCM_RATE_5512; | ||
378 | struct snd_interval *c = hw_param_interval(p, SNDRV_PCM_HW_PARAM_CHANNELS); | ||
379 | |||
380 | switch (c->max) { | ||
381 | case 6: | ||
382 | rate_mask &= aaci_rate_mask(aaci, ACSTREAM_LFE); | ||
383 | case 4: | ||
384 | rate_mask &= aaci_rate_mask(aaci, ACSTREAM_SURROUND); | ||
385 | case 2: | ||
386 | rate_mask &= aaci_rate_mask(aaci, ACSTREAM_FRONT); | ||
387 | } | ||
388 | |||
389 | return snd_interval_list(hw_param_interval(p, rule->var), | ||
390 | ARRAY_SIZE(rate_list), rate_list, | ||
391 | rate_mask); | ||
392 | } | ||
393 | |||
394 | static struct snd_pcm_hardware aaci_hw_info = { | 341 | static struct snd_pcm_hardware aaci_hw_info = { |
395 | .info = SNDRV_PCM_INFO_MMAP | | 342 | .info = SNDRV_PCM_INFO_MMAP | |
396 | SNDRV_PCM_INFO_MMAP_VALID | | 343 | SNDRV_PCM_INFO_MMAP_VALID | |
@@ -404,10 +351,7 @@ static struct snd_pcm_hardware aaci_hw_info = { | |||
404 | */ | 351 | */ |
405 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 352 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
406 | 353 | ||
407 | /* should this be continuous or knot? */ | 354 | /* rates are setup from the AC'97 codec */ |
408 | .rates = SNDRV_PCM_RATE_CONTINUOUS, | ||
409 | .rate_max = 48000, | ||
410 | .rate_min = 4000, | ||
411 | .channels_min = 2, | 355 | .channels_min = 2, |
412 | .channels_max = 6, | 356 | .channels_max = 6, |
413 | .buffer_bytes_max = 64 * 1024, | 357 | .buffer_bytes_max = 64 * 1024, |
@@ -427,6 +371,12 @@ static int __aaci_pcm_open(struct aaci *aaci, | |||
427 | aacirun->substream = substream; | 371 | aacirun->substream = substream; |
428 | runtime->private_data = aacirun; | 372 | runtime->private_data = aacirun; |
429 | runtime->hw = aaci_hw_info; | 373 | runtime->hw = aaci_hw_info; |
374 | runtime->hw.rates = aacirun->pcm->rates; | ||
375 | snd_pcm_limit_hw_rates(runtime); | ||
376 | |||
377 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && | ||
378 | aacirun->pcm->r[1].slots) | ||
379 | snd_ac97_pcm_double_rate_rules(runtime); | ||
430 | 380 | ||
431 | /* | 381 | /* |
432 | * FIXME: ALSA specifies fifo_size in bytes. If we're in normal | 382 | * FIXME: ALSA specifies fifo_size in bytes. If we're in normal |
@@ -437,17 +387,6 @@ static int __aaci_pcm_open(struct aaci *aaci, | |||
437 | */ | 387 | */ |
438 | runtime->hw.fifo_size = aaci->fifosize * 2; | 388 | runtime->hw.fifo_size = aaci->fifosize * 2; |
439 | 389 | ||
440 | /* | ||
441 | * Add rule describing hardware rate dependency | ||
442 | * on the number of channels. | ||
443 | */ | ||
444 | ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | ||
445 | aaci_rule_rate_by_channels, aaci, | ||
446 | SNDRV_PCM_HW_PARAM_CHANNELS, | ||
447 | SNDRV_PCM_HW_PARAM_RATE, -1); | ||
448 | if (ret) | ||
449 | goto out; | ||
450 | |||
451 | ret = request_irq(aaci->dev->irq[0], aaci_irq, IRQF_SHARED|IRQF_DISABLED, | 390 | ret = request_irq(aaci->dev->irq[0], aaci_irq, IRQF_SHARED|IRQF_DISABLED, |
452 | DRIVER_NAME, aaci); | 391 | DRIVER_NAME, aaci); |
453 | if (ret) | 392 | if (ret) |
@@ -492,7 +431,7 @@ static int aaci_pcm_hw_free(struct snd_pcm_substream *substream) | |||
492 | /* | 431 | /* |
493 | * Clear out the DMA and any allocated buffers. | 432 | * Clear out the DMA and any allocated buffers. |
494 | */ | 433 | */ |
495 | devdma_hw_free(NULL, substream); | 434 | snd_pcm_lib_free_pages(substream); |
496 | 435 | ||
497 | return 0; | 436 | return 0; |
498 | } | 437 | } |
@@ -502,29 +441,32 @@ static int aaci_pcm_hw_params(struct snd_pcm_substream *substream, | |||
502 | struct snd_pcm_hw_params *params) | 441 | struct snd_pcm_hw_params *params) |
503 | { | 442 | { |
504 | int err; | 443 | int err; |
444 | struct aaci *aaci = substream->private_data; | ||
505 | 445 | ||
506 | aaci_pcm_hw_free(substream); | 446 | aaci_pcm_hw_free(substream); |
447 | if (aacirun->pcm_open) { | ||
448 | snd_ac97_pcm_close(aacirun->pcm); | ||
449 | aacirun->pcm_open = 0; | ||
450 | } | ||
507 | 451 | ||
508 | err = devdma_hw_alloc(NULL, substream, | 452 | err = snd_pcm_lib_malloc_pages(substream, |
509 | params_buffer_bytes(params)); | 453 | params_buffer_bytes(params)); |
510 | if (err < 0) | 454 | if (err >= 0) { |
511 | goto out; | 455 | unsigned int rate = params_rate(params); |
456 | int dbl = rate > 48000; | ||
512 | 457 | ||
513 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 458 | err = snd_ac97_pcm_open(aacirun->pcm, rate, |
514 | err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params), | ||
515 | params_channels(params), | 459 | params_channels(params), |
516 | aacirun->pcm->r[0].slots); | 460 | aacirun->pcm->r[dbl].slots); |
517 | else | ||
518 | err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params), | ||
519 | params_channels(params), | ||
520 | aacirun->pcm->r[1].slots); | ||
521 | 461 | ||
522 | if (err) | 462 | aacirun->pcm_open = err == 0; |
523 | goto out; | 463 | aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16; |
464 | aacirun->fifosz = aaci->fifosize * 4; | ||
524 | 465 | ||
525 | aacirun->pcm_open = 1; | 466 | if (aacirun->cr & CR_COMPACT) |
467 | aacirun->fifosz >>= 1; | ||
468 | } | ||
526 | 469 | ||
527 | out: | ||
528 | return err; | 470 | return err; |
529 | } | 471 | } |
530 | 472 | ||
@@ -533,8 +475,8 @@ static int aaci_pcm_prepare(struct snd_pcm_substream *substream) | |||
533 | struct snd_pcm_runtime *runtime = substream->runtime; | 475 | struct snd_pcm_runtime *runtime = substream->runtime; |
534 | struct aaci_runtime *aacirun = runtime->private_data; | 476 | struct aaci_runtime *aacirun = runtime->private_data; |
535 | 477 | ||
536 | aacirun->start = (void *)runtime->dma_area; | 478 | aacirun->start = runtime->dma_area; |
537 | aacirun->end = aacirun->start + runtime->dma_bytes; | 479 | aacirun->end = aacirun->start + snd_pcm_lib_buffer_bytes(substream); |
538 | aacirun->ptr = aacirun->start; | 480 | aacirun->ptr = aacirun->start; |
539 | aacirun->period = | 481 | aacirun->period = |
540 | aacirun->bytes = frames_to_bytes(runtime, runtime->period_size); | 482 | aacirun->bytes = frames_to_bytes(runtime, runtime->period_size); |
@@ -551,11 +493,6 @@ static snd_pcm_uframes_t aaci_pcm_pointer(struct snd_pcm_substream *substream) | |||
551 | return bytes_to_frames(runtime, bytes); | 493 | return bytes_to_frames(runtime, bytes); |
552 | } | 494 | } |
553 | 495 | ||
554 | static int aaci_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma) | ||
555 | { | ||
556 | return devdma_mmap(NULL, substream, vma); | ||
557 | } | ||
558 | |||
559 | 496 | ||
560 | /* | 497 | /* |
561 | * Playback specific ALSA stuff | 498 | * Playback specific ALSA stuff |
@@ -624,7 +561,6 @@ static int aaci_pcm_open(struct snd_pcm_substream *substream) | |||
624 | static int aaci_pcm_playback_hw_params(struct snd_pcm_substream *substream, | 561 | static int aaci_pcm_playback_hw_params(struct snd_pcm_substream *substream, |
625 | struct snd_pcm_hw_params *params) | 562 | struct snd_pcm_hw_params *params) |
626 | { | 563 | { |
627 | struct aaci *aaci = substream->private_data; | ||
628 | struct aaci_runtime *aacirun = substream->runtime->private_data; | 564 | struct aaci_runtime *aacirun = substream->runtime->private_data; |
629 | unsigned int channels = params_channels(params); | 565 | unsigned int channels = params_channels(params); |
630 | int ret; | 566 | int ret; |
@@ -638,14 +574,9 @@ static int aaci_pcm_playback_hw_params(struct snd_pcm_substream *substream, | |||
638 | * Enable FIFO, compact mode, 16 bits per sample. | 574 | * Enable FIFO, compact mode, 16 bits per sample. |
639 | * FIXME: double rate slots? | 575 | * FIXME: double rate slots? |
640 | */ | 576 | */ |
641 | if (ret >= 0) { | 577 | if (ret >= 0) |
642 | aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16; | ||
643 | aacirun->cr |= channels_to_txmask[channels]; | 578 | aacirun->cr |= channels_to_txmask[channels]; |
644 | 579 | ||
645 | aacirun->fifosz = aaci->fifosize * 4; | ||
646 | if (aacirun->cr & CR_COMPACT) | ||
647 | aacirun->fifosz >>= 1; | ||
648 | } | ||
649 | return ret; | 580 | return ret; |
650 | } | 581 | } |
651 | 582 | ||
@@ -657,7 +588,7 @@ static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun) | |||
657 | ie &= ~(IE_URIE|IE_TXIE); | 588 | ie &= ~(IE_URIE|IE_TXIE); |
658 | writel(ie, aacirun->base + AACI_IE); | 589 | writel(ie, aacirun->base + AACI_IE); |
659 | aacirun->cr &= ~CR_EN; | 590 | aacirun->cr &= ~CR_EN; |
660 | aaci_chan_wait_ready(aacirun); | 591 | aaci_chan_wait_ready(aacirun, SR_TXB); |
661 | writel(aacirun->cr, aacirun->base + AACI_TXCR); | 592 | writel(aacirun->cr, aacirun->base + AACI_TXCR); |
662 | } | 593 | } |
663 | 594 | ||
@@ -665,7 +596,7 @@ static void aaci_pcm_playback_start(struct aaci_runtime *aacirun) | |||
665 | { | 596 | { |
666 | u32 ie; | 597 | u32 ie; |
667 | 598 | ||
668 | aaci_chan_wait_ready(aacirun); | 599 | aaci_chan_wait_ready(aacirun, SR_TXB); |
669 | aacirun->cr |= CR_EN; | 600 | aacirun->cr |= CR_EN; |
670 | 601 | ||
671 | ie = readl(aacirun->base + AACI_IE); | 602 | ie = readl(aacirun->base + AACI_IE); |
@@ -676,12 +607,12 @@ static void aaci_pcm_playback_start(struct aaci_runtime *aacirun) | |||
676 | 607 | ||
677 | static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd) | 608 | static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd) |
678 | { | 609 | { |
679 | struct aaci *aaci = substream->private_data; | ||
680 | struct aaci_runtime *aacirun = substream->runtime->private_data; | 610 | struct aaci_runtime *aacirun = substream->runtime->private_data; |
681 | unsigned long flags; | 611 | unsigned long flags; |
682 | int ret = 0; | 612 | int ret = 0; |
683 | 613 | ||
684 | spin_lock_irqsave(&aaci->lock, flags); | 614 | spin_lock_irqsave(&aacirun->lock, flags); |
615 | |||
685 | switch (cmd) { | 616 | switch (cmd) { |
686 | case SNDRV_PCM_TRIGGER_START: | 617 | case SNDRV_PCM_TRIGGER_START: |
687 | aaci_pcm_playback_start(aacirun); | 618 | aaci_pcm_playback_start(aacirun); |
@@ -708,7 +639,8 @@ static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cm | |||
708 | default: | 639 | default: |
709 | ret = -EINVAL; | 640 | ret = -EINVAL; |
710 | } | 641 | } |
711 | spin_unlock_irqrestore(&aaci->lock, flags); | 642 | |
643 | spin_unlock_irqrestore(&aacirun->lock, flags); | ||
712 | 644 | ||
713 | return ret; | 645 | return ret; |
714 | } | 646 | } |
@@ -722,29 +654,19 @@ static struct snd_pcm_ops aaci_playback_ops = { | |||
722 | .prepare = aaci_pcm_prepare, | 654 | .prepare = aaci_pcm_prepare, |
723 | .trigger = aaci_pcm_playback_trigger, | 655 | .trigger = aaci_pcm_playback_trigger, |
724 | .pointer = aaci_pcm_pointer, | 656 | .pointer = aaci_pcm_pointer, |
725 | .mmap = aaci_pcm_mmap, | ||
726 | }; | 657 | }; |
727 | 658 | ||
728 | static int aaci_pcm_capture_hw_params(struct snd_pcm_substream *substream, | 659 | static int aaci_pcm_capture_hw_params(struct snd_pcm_substream *substream, |
729 | struct snd_pcm_hw_params *params) | 660 | struct snd_pcm_hw_params *params) |
730 | { | 661 | { |
731 | struct aaci *aaci = substream->private_data; | ||
732 | struct aaci_runtime *aacirun = substream->runtime->private_data; | 662 | struct aaci_runtime *aacirun = substream->runtime->private_data; |
733 | int ret; | 663 | int ret; |
734 | 664 | ||
735 | ret = aaci_pcm_hw_params(substream, aacirun, params); | 665 | ret = aaci_pcm_hw_params(substream, aacirun, params); |
736 | 666 | if (ret >= 0) | |
737 | if (ret >= 0) { | ||
738 | aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16; | ||
739 | |||
740 | /* Line in record: slot 3 and 4 */ | 667 | /* Line in record: slot 3 and 4 */ |
741 | aacirun->cr |= CR_SL3 | CR_SL4; | 668 | aacirun->cr |= CR_SL3 | CR_SL4; |
742 | 669 | ||
743 | aacirun->fifosz = aaci->fifosize * 4; | ||
744 | |||
745 | if (aacirun->cr & CR_COMPACT) | ||
746 | aacirun->fifosz >>= 1; | ||
747 | } | ||
748 | return ret; | 670 | return ret; |
749 | } | 671 | } |
750 | 672 | ||
@@ -752,7 +674,7 @@ static void aaci_pcm_capture_stop(struct aaci_runtime *aacirun) | |||
752 | { | 674 | { |
753 | u32 ie; | 675 | u32 ie; |
754 | 676 | ||
755 | aaci_chan_wait_ready(aacirun); | 677 | aaci_chan_wait_ready(aacirun, SR_RXB); |
756 | 678 | ||
757 | ie = readl(aacirun->base + AACI_IE); | 679 | ie = readl(aacirun->base + AACI_IE); |
758 | ie &= ~(IE_ORIE | IE_RXIE); | 680 | ie &= ~(IE_ORIE | IE_RXIE); |
@@ -767,7 +689,7 @@ static void aaci_pcm_capture_start(struct aaci_runtime *aacirun) | |||
767 | { | 689 | { |
768 | u32 ie; | 690 | u32 ie; |
769 | 691 | ||
770 | aaci_chan_wait_ready(aacirun); | 692 | aaci_chan_wait_ready(aacirun, SR_RXB); |
771 | 693 | ||
772 | #ifdef DEBUG | 694 | #ifdef DEBUG |
773 | /* RX Timeout value: bits 28:17 in RXCR */ | 695 | /* RX Timeout value: bits 28:17 in RXCR */ |
@@ -784,12 +706,11 @@ static void aaci_pcm_capture_start(struct aaci_runtime *aacirun) | |||
784 | 706 | ||
785 | static int aaci_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd) | 707 | static int aaci_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd) |
786 | { | 708 | { |
787 | struct aaci *aaci = substream->private_data; | ||
788 | struct aaci_runtime *aacirun = substream->runtime->private_data; | 709 | struct aaci_runtime *aacirun = substream->runtime->private_data; |
789 | unsigned long flags; | 710 | unsigned long flags; |
790 | int ret = 0; | 711 | int ret = 0; |
791 | 712 | ||
792 | spin_lock_irqsave(&aaci->lock, flags); | 713 | spin_lock_irqsave(&aacirun->lock, flags); |
793 | 714 | ||
794 | switch (cmd) { | 715 | switch (cmd) { |
795 | case SNDRV_PCM_TRIGGER_START: | 716 | case SNDRV_PCM_TRIGGER_START: |
@@ -818,7 +739,7 @@ static int aaci_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd | |||
818 | ret = -EINVAL; | 739 | ret = -EINVAL; |
819 | } | 740 | } |
820 | 741 | ||
821 | spin_unlock_irqrestore(&aaci->lock, flags); | 742 | spin_unlock_irqrestore(&aacirun->lock, flags); |
822 | 743 | ||
823 | return ret; | 744 | return ret; |
824 | } | 745 | } |
@@ -850,7 +771,6 @@ static struct snd_pcm_ops aaci_capture_ops = { | |||
850 | .prepare = aaci_pcm_capture_prepare, | 771 | .prepare = aaci_pcm_capture_prepare, |
851 | .trigger = aaci_pcm_capture_trigger, | 772 | .trigger = aaci_pcm_capture_trigger, |
852 | .pointer = aaci_pcm_pointer, | 773 | .pointer = aaci_pcm_pointer, |
853 | .mmap = aaci_pcm_mmap, | ||
854 | }; | 774 | }; |
855 | 775 | ||
856 | /* | 776 | /* |
@@ -902,6 +822,12 @@ static struct ac97_pcm ac97_defs[] __devinitdata = { | |||
902 | (1 << AC97_SLOT_PCM_SRIGHT) | | 822 | (1 << AC97_SLOT_PCM_SRIGHT) | |
903 | (1 << AC97_SLOT_LFE), | 823 | (1 << AC97_SLOT_LFE), |
904 | }, | 824 | }, |
825 | [1] = { | ||
826 | .slots = (1 << AC97_SLOT_PCM_LEFT) | | ||
827 | (1 << AC97_SLOT_PCM_RIGHT) | | ||
828 | (1 << AC97_SLOT_PCM_LEFT_0) | | ||
829 | (1 << AC97_SLOT_PCM_RIGHT_0), | ||
830 | }, | ||
905 | }, | 831 | }, |
906 | }, | 832 | }, |
907 | [1] = { /* PCM in */ | 833 | [1] = { /* PCM in */ |
@@ -1014,7 +940,6 @@ static struct aaci * __devinit aaci_init_card(struct amba_device *dev) | |||
1014 | 940 | ||
1015 | aaci = card->private_data; | 941 | aaci = card->private_data; |
1016 | mutex_init(&aaci->ac97_sem); | 942 | mutex_init(&aaci->ac97_sem); |
1017 | spin_lock_init(&aaci->lock); | ||
1018 | aaci->card = card; | 943 | aaci->card = card; |
1019 | aaci->dev = dev; | 944 | aaci->dev = dev; |
1020 | 945 | ||
@@ -1040,6 +965,8 @@ static int __devinit aaci_init_pcm(struct aaci *aaci) | |||
1040 | 965 | ||
1041 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops); | 966 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops); |
1042 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &aaci_capture_ops); | 967 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &aaci_capture_ops); |
968 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | ||
969 | NULL, 0, 64 * 1024); | ||
1043 | } | 970 | } |
1044 | 971 | ||
1045 | return ret; | 972 | return ret; |
@@ -1099,12 +1026,14 @@ static int __devinit aaci_probe(struct amba_device *dev, struct amba_id *id) | |||
1099 | /* | 1026 | /* |
1100 | * Playback uses AACI channel 0 | 1027 | * Playback uses AACI channel 0 |
1101 | */ | 1028 | */ |
1029 | spin_lock_init(&aaci->playback.lock); | ||
1102 | aaci->playback.base = aaci->base + AACI_CSCH1; | 1030 | aaci->playback.base = aaci->base + AACI_CSCH1; |
1103 | aaci->playback.fifo = aaci->base + AACI_DR1; | 1031 | aaci->playback.fifo = aaci->base + AACI_DR1; |
1104 | 1032 | ||
1105 | /* | 1033 | /* |
1106 | * Capture uses AACI channel 0 | 1034 | * Capture uses AACI channel 0 |
1107 | */ | 1035 | */ |
1036 | spin_lock_init(&aaci->capture.lock); | ||
1108 | aaci->capture.base = aaci->base + AACI_CSCH1; | 1037 | aaci->capture.base = aaci->base + AACI_CSCH1; |
1109 | aaci->capture.fifo = aaci->base + AACI_DR1; | 1038 | aaci->capture.fifo = aaci->base + AACI_DR1; |
1110 | 1039 | ||