diff options
Diffstat (limited to 'sound/arm')
-rw-r--r-- | sound/arm/aaci.c | 285 | ||||
-rw-r--r-- | sound/arm/aaci.h | 9 |
2 files changed, 136 insertions, 158 deletions
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c index 7c1fc64cb53d..d0cead38d5fb 100644 --- a/sound/arm/aaci.c +++ b/sound/arm/aaci.c | |||
@@ -210,6 +210,7 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) | |||
210 | 210 | ||
211 | if (mask & ISR_RXINTR) { | 211 | if (mask & ISR_RXINTR) { |
212 | struct aaci_runtime *aacirun = &aaci->capture; | 212 | struct aaci_runtime *aacirun = &aaci->capture; |
213 | bool period_elapsed = false; | ||
213 | void *ptr; | 214 | void *ptr; |
214 | 215 | ||
215 | if (!aacirun->substream || !aacirun->start) { | 216 | if (!aacirun->substream || !aacirun->start) { |
@@ -222,15 +223,12 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) | |||
222 | 223 | ||
223 | ptr = aacirun->ptr; | 224 | ptr = aacirun->ptr; |
224 | do { | 225 | do { |
225 | unsigned int len = aacirun->fifosz; | 226 | unsigned int len = aacirun->fifo_bytes; |
226 | u32 val; | 227 | u32 val; |
227 | 228 | ||
228 | if (aacirun->bytes <= 0) { | 229 | if (aacirun->bytes <= 0) { |
229 | aacirun->bytes += aacirun->period; | 230 | aacirun->bytes += aacirun->period; |
230 | aacirun->ptr = ptr; | 231 | period_elapsed = true; |
231 | spin_unlock(&aacirun->lock); | ||
232 | snd_pcm_period_elapsed(aacirun->substream); | ||
233 | spin_lock(&aacirun->lock); | ||
234 | } | 232 | } |
235 | if (!(aacirun->cr & CR_EN)) | 233 | if (!(aacirun->cr & CR_EN)) |
236 | break; | 234 | break; |
@@ -260,6 +258,9 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) | |||
260 | aacirun->ptr = ptr; | 258 | aacirun->ptr = ptr; |
261 | 259 | ||
262 | spin_unlock(&aacirun->lock); | 260 | spin_unlock(&aacirun->lock); |
261 | |||
262 | if (period_elapsed) | ||
263 | snd_pcm_period_elapsed(aacirun->substream); | ||
263 | } | 264 | } |
264 | 265 | ||
265 | if (mask & ISR_URINTR) { | 266 | if (mask & ISR_URINTR) { |
@@ -269,6 +270,7 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) | |||
269 | 270 | ||
270 | if (mask & ISR_TXINTR) { | 271 | if (mask & ISR_TXINTR) { |
271 | struct aaci_runtime *aacirun = &aaci->playback; | 272 | struct aaci_runtime *aacirun = &aaci->playback; |
273 | bool period_elapsed = false; | ||
272 | void *ptr; | 274 | void *ptr; |
273 | 275 | ||
274 | if (!aacirun->substream || !aacirun->start) { | 276 | if (!aacirun->substream || !aacirun->start) { |
@@ -281,15 +283,12 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) | |||
281 | 283 | ||
282 | ptr = aacirun->ptr; | 284 | ptr = aacirun->ptr; |
283 | do { | 285 | do { |
284 | unsigned int len = aacirun->fifosz; | 286 | unsigned int len = aacirun->fifo_bytes; |
285 | u32 val; | 287 | u32 val; |
286 | 288 | ||
287 | if (aacirun->bytes <= 0) { | 289 | if (aacirun->bytes <= 0) { |
288 | aacirun->bytes += aacirun->period; | 290 | aacirun->bytes += aacirun->period; |
289 | aacirun->ptr = ptr; | 291 | period_elapsed = true; |
290 | spin_unlock(&aacirun->lock); | ||
291 | snd_pcm_period_elapsed(aacirun->substream); | ||
292 | spin_lock(&aacirun->lock); | ||
293 | } | 292 | } |
294 | if (!(aacirun->cr & CR_EN)) | 293 | if (!(aacirun->cr & CR_EN)) |
295 | break; | 294 | break; |
@@ -319,6 +318,9 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) | |||
319 | aacirun->ptr = ptr; | 318 | aacirun->ptr = ptr; |
320 | 319 | ||
321 | spin_unlock(&aacirun->lock); | 320 | spin_unlock(&aacirun->lock); |
321 | |||
322 | if (period_elapsed) | ||
323 | snd_pcm_period_elapsed(aacirun->substream); | ||
322 | } | 324 | } |
323 | } | 325 | } |
324 | 326 | ||
@@ -361,7 +363,7 @@ static struct snd_pcm_hardware aaci_hw_info = { | |||
361 | 363 | ||
362 | /* rates are setup from the AC'97 codec */ | 364 | /* rates are setup from the AC'97 codec */ |
363 | .channels_min = 2, | 365 | .channels_min = 2, |
364 | .channels_max = 6, | 366 | .channels_max = 2, |
365 | .buffer_bytes_max = 64 * 1024, | 367 | .buffer_bytes_max = 64 * 1024, |
366 | .period_bytes_min = 256, | 368 | .period_bytes_min = 256, |
367 | .period_bytes_max = PAGE_SIZE, | 369 | .period_bytes_max = PAGE_SIZE, |
@@ -369,12 +371,46 @@ static struct snd_pcm_hardware aaci_hw_info = { | |||
369 | .periods_max = PAGE_SIZE / 16, | 371 | .periods_max = PAGE_SIZE / 16, |
370 | }; | 372 | }; |
371 | 373 | ||
372 | static int __aaci_pcm_open(struct aaci *aaci, | 374 | /* |
373 | struct snd_pcm_substream *substream, | 375 | * We can support two and four channel audio. Unfortunately |
374 | struct aaci_runtime *aacirun) | 376 | * six channel audio requires a non-standard channel ordering: |
377 | * 2 -> FL(3), FR(4) | ||
378 | * 4 -> FL(3), FR(4), SL(7), SR(8) | ||
379 | * 6 -> FL(3), FR(4), SL(7), SR(8), C(6), LFE(9) (required) | ||
380 | * FL(3), FR(4), C(6), SL(7), SR(8), LFE(9) (actual) | ||
381 | * This requires an ALSA configuration file to correct. | ||
382 | */ | ||
383 | static int aaci_rule_channels(struct snd_pcm_hw_params *p, | ||
384 | struct snd_pcm_hw_rule *rule) | ||
385 | { | ||
386 | static unsigned int channel_list[] = { 2, 4, 6 }; | ||
387 | struct aaci *aaci = rule->private; | ||
388 | unsigned int mask = 1 << 0, slots; | ||
389 | |||
390 | /* pcms[0] is the our 5.1 PCM instance. */ | ||
391 | slots = aaci->ac97_bus->pcms[0].r[0].slots; | ||
392 | if (slots & (1 << AC97_SLOT_PCM_SLEFT)) { | ||
393 | mask |= 1 << 1; | ||
394 | if (slots & (1 << AC97_SLOT_LFE)) | ||
395 | mask |= 1 << 2; | ||
396 | } | ||
397 | |||
398 | return snd_interval_list(hw_param_interval(p, rule->var), | ||
399 | ARRAY_SIZE(channel_list), channel_list, mask); | ||
400 | } | ||
401 | |||
402 | static int aaci_pcm_open(struct snd_pcm_substream *substream) | ||
375 | { | 403 | { |
376 | struct snd_pcm_runtime *runtime = substream->runtime; | 404 | struct snd_pcm_runtime *runtime = substream->runtime; |
377 | int ret; | 405 | struct aaci *aaci = substream->private_data; |
406 | struct aaci_runtime *aacirun; | ||
407 | int ret = 0; | ||
408 | |||
409 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
410 | aacirun = &aaci->playback; | ||
411 | } else { | ||
412 | aacirun = &aaci->capture; | ||
413 | } | ||
378 | 414 | ||
379 | aacirun->substream = substream; | 415 | aacirun->substream = substream; |
380 | runtime->private_data = aacirun; | 416 | runtime->private_data = aacirun; |
@@ -382,27 +418,37 @@ static int __aaci_pcm_open(struct aaci *aaci, | |||
382 | runtime->hw.rates = aacirun->pcm->rates; | 418 | runtime->hw.rates = aacirun->pcm->rates; |
383 | snd_pcm_limit_hw_rates(runtime); | 419 | snd_pcm_limit_hw_rates(runtime); |
384 | 420 | ||
385 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && | 421 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
386 | aacirun->pcm->r[1].slots) | 422 | runtime->hw.channels_max = 6; |
387 | snd_ac97_pcm_double_rate_rules(runtime); | 423 | |
424 | /* Add rule describing channel dependency. */ | ||
425 | ret = snd_pcm_hw_rule_add(substream->runtime, 0, | ||
426 | SNDRV_PCM_HW_PARAM_CHANNELS, | ||
427 | aaci_rule_channels, aaci, | ||
428 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | ||
429 | if (ret) | ||
430 | return ret; | ||
431 | |||
432 | if (aacirun->pcm->r[1].slots) | ||
433 | snd_ac97_pcm_double_rate_rules(runtime); | ||
434 | } | ||
388 | 435 | ||
389 | /* | 436 | /* |
390 | * FIXME: ALSA specifies fifo_size in bytes. If we're in normal | 437 | * ALSA wants the byte-size of the FIFOs. As we only support |
391 | * mode, each 32-bit word contains one sample. If we're in | 438 | * 16-bit samples, this is twice the FIFO depth irrespective |
392 | * compact mode, each 32-bit word contains two samples, effectively | 439 | * of whether it's in compact mode or not. |
393 | * halving the FIFO size. However, we don't know for sure which | ||
394 | * we'll be using at this point. We set this to the lower limit. | ||
395 | */ | 440 | */ |
396 | runtime->hw.fifo_size = aaci->fifosize * 2; | 441 | runtime->hw.fifo_size = aaci->fifo_depth * 2; |
397 | 442 | ||
398 | ret = request_irq(aaci->dev->irq[0], aaci_irq, IRQF_SHARED|IRQF_DISABLED, | 443 | mutex_lock(&aaci->irq_lock); |
399 | DRIVER_NAME, aaci); | 444 | if (!aaci->users++) { |
400 | if (ret) | 445 | ret = request_irq(aaci->dev->irq[0], aaci_irq, |
401 | goto out; | 446 | IRQF_SHARED | IRQF_DISABLED, DRIVER_NAME, aaci); |
402 | 447 | if (ret != 0) | |
403 | return 0; | 448 | aaci->users--; |
449 | } | ||
450 | mutex_unlock(&aaci->irq_lock); | ||
404 | 451 | ||
405 | out: | ||
406 | return ret; | 452 | return ret; |
407 | } | 453 | } |
408 | 454 | ||
@@ -418,7 +464,11 @@ static int aaci_pcm_close(struct snd_pcm_substream *substream) | |||
418 | WARN_ON(aacirun->cr & CR_EN); | 464 | WARN_ON(aacirun->cr & CR_EN); |
419 | 465 | ||
420 | aacirun->substream = NULL; | 466 | aacirun->substream = NULL; |
421 | free_irq(aaci->dev->irq[0], aaci); | 467 | |
468 | mutex_lock(&aaci->irq_lock); | ||
469 | if (!--aaci->users) | ||
470 | free_irq(aaci->dev->irq[0], aaci); | ||
471 | mutex_unlock(&aaci->irq_lock); | ||
422 | 472 | ||
423 | return 0; | 473 | return 0; |
424 | } | 474 | } |
@@ -444,12 +494,21 @@ static int aaci_pcm_hw_free(struct snd_pcm_substream *substream) | |||
444 | return 0; | 494 | return 0; |
445 | } | 495 | } |
446 | 496 | ||
497 | /* Channel to slot mask */ | ||
498 | static const u32 channels_to_slotmask[] = { | ||
499 | [2] = CR_SL3 | CR_SL4, | ||
500 | [4] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8, | ||
501 | [6] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8 | CR_SL6 | CR_SL9, | ||
502 | }; | ||
503 | |||
447 | static int aaci_pcm_hw_params(struct snd_pcm_substream *substream, | 504 | static int aaci_pcm_hw_params(struct snd_pcm_substream *substream, |
448 | struct aaci_runtime *aacirun, | ||
449 | struct snd_pcm_hw_params *params) | 505 | struct snd_pcm_hw_params *params) |
450 | { | 506 | { |
507 | struct aaci_runtime *aacirun = substream->runtime->private_data; | ||
508 | unsigned int channels = params_channels(params); | ||
509 | unsigned int rate = params_rate(params); | ||
510 | int dbl = rate > 48000; | ||
451 | int err; | 511 | int err; |
452 | struct aaci *aaci = substream->private_data; | ||
453 | 512 | ||
454 | aaci_pcm_hw_free(substream); | 513 | aaci_pcm_hw_free(substream); |
455 | if (aacirun->pcm_open) { | 514 | if (aacirun->pcm_open) { |
@@ -457,22 +516,28 @@ static int aaci_pcm_hw_params(struct snd_pcm_substream *substream, | |||
457 | aacirun->pcm_open = 0; | 516 | aacirun->pcm_open = 0; |
458 | } | 517 | } |
459 | 518 | ||
519 | /* channels is already limited to 2, 4, or 6 by aaci_rule_channels */ | ||
520 | if (dbl && channels != 2) | ||
521 | return -EINVAL; | ||
522 | |||
460 | err = snd_pcm_lib_malloc_pages(substream, | 523 | err = snd_pcm_lib_malloc_pages(substream, |
461 | params_buffer_bytes(params)); | 524 | params_buffer_bytes(params)); |
462 | if (err >= 0) { | 525 | if (err >= 0) { |
463 | unsigned int rate = params_rate(params); | 526 | struct aaci *aaci = substream->private_data; |
464 | int dbl = rate > 48000; | ||
465 | 527 | ||
466 | err = snd_ac97_pcm_open(aacirun->pcm, rate, | 528 | err = snd_ac97_pcm_open(aacirun->pcm, rate, channels, |
467 | params_channels(params), | ||
468 | aacirun->pcm->r[dbl].slots); | 529 | aacirun->pcm->r[dbl].slots); |
469 | 530 | ||
470 | aacirun->pcm_open = err == 0; | 531 | aacirun->pcm_open = err == 0; |
471 | aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16; | 532 | aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16; |
472 | aacirun->fifosz = aaci->fifosize * 4; | 533 | aacirun->cr |= channels_to_slotmask[channels + dbl * 2]; |
473 | 534 | ||
474 | if (aacirun->cr & CR_COMPACT) | 535 | /* |
475 | aacirun->fifosz >>= 1; | 536 | * fifo_bytes is the number of bytes we transfer to/from |
537 | * the FIFO, including padding. So that's x4. As we're | ||
538 | * in compact mode, the FIFO is half the size. | ||
539 | */ | ||
540 | aacirun->fifo_bytes = aaci->fifo_depth * 4 / 2; | ||
476 | } | 541 | } |
477 | 542 | ||
478 | return err; | 543 | return err; |
@@ -483,11 +548,11 @@ static int aaci_pcm_prepare(struct snd_pcm_substream *substream) | |||
483 | struct snd_pcm_runtime *runtime = substream->runtime; | 548 | struct snd_pcm_runtime *runtime = substream->runtime; |
484 | struct aaci_runtime *aacirun = runtime->private_data; | 549 | struct aaci_runtime *aacirun = runtime->private_data; |
485 | 550 | ||
551 | aacirun->period = snd_pcm_lib_period_bytes(substream); | ||
486 | aacirun->start = runtime->dma_area; | 552 | aacirun->start = runtime->dma_area; |
487 | aacirun->end = aacirun->start + snd_pcm_lib_buffer_bytes(substream); | 553 | aacirun->end = aacirun->start + snd_pcm_lib_buffer_bytes(substream); |
488 | aacirun->ptr = aacirun->start; | 554 | aacirun->ptr = aacirun->start; |
489 | aacirun->period = | 555 | aacirun->bytes = aacirun->period; |
490 | aacirun->bytes = frames_to_bytes(runtime, runtime->period_size); | ||
491 | 556 | ||
492 | return 0; | 557 | return 0; |
493 | } | 558 | } |
@@ -505,89 +570,6 @@ static snd_pcm_uframes_t aaci_pcm_pointer(struct snd_pcm_substream *substream) | |||
505 | /* | 570 | /* |
506 | * Playback specific ALSA stuff | 571 | * Playback specific ALSA stuff |
507 | */ | 572 | */ |
508 | static const u32 channels_to_txmask[] = { | ||
509 | [2] = CR_SL3 | CR_SL4, | ||
510 | [4] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8, | ||
511 | [6] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8 | CR_SL6 | CR_SL9, | ||
512 | }; | ||
513 | |||
514 | /* | ||
515 | * We can support two and four channel audio. Unfortunately | ||
516 | * six channel audio requires a non-standard channel ordering: | ||
517 | * 2 -> FL(3), FR(4) | ||
518 | * 4 -> FL(3), FR(4), SL(7), SR(8) | ||
519 | * 6 -> FL(3), FR(4), SL(7), SR(8), C(6), LFE(9) (required) | ||
520 | * FL(3), FR(4), C(6), SL(7), SR(8), LFE(9) (actual) | ||
521 | * This requires an ALSA configuration file to correct. | ||
522 | */ | ||
523 | static unsigned int channel_list[] = { 2, 4, 6 }; | ||
524 | |||
525 | static int | ||
526 | aaci_rule_channels(struct snd_pcm_hw_params *p, struct snd_pcm_hw_rule *rule) | ||
527 | { | ||
528 | struct aaci *aaci = rule->private; | ||
529 | unsigned int chan_mask = 1 << 0, slots; | ||
530 | |||
531 | /* | ||
532 | * pcms[0] is the our 5.1 PCM instance. | ||
533 | */ | ||
534 | slots = aaci->ac97_bus->pcms[0].r[0].slots; | ||
535 | if (slots & (1 << AC97_SLOT_PCM_SLEFT)) { | ||
536 | chan_mask |= 1 << 1; | ||
537 | if (slots & (1 << AC97_SLOT_LFE)) | ||
538 | chan_mask |= 1 << 2; | ||
539 | } | ||
540 | |||
541 | return snd_interval_list(hw_param_interval(p, rule->var), | ||
542 | ARRAY_SIZE(channel_list), channel_list, | ||
543 | chan_mask); | ||
544 | } | ||
545 | |||
546 | static int aaci_pcm_open(struct snd_pcm_substream *substream) | ||
547 | { | ||
548 | struct aaci *aaci = substream->private_data; | ||
549 | int ret; | ||
550 | |||
551 | /* | ||
552 | * Add rule describing channel dependency. | ||
553 | */ | ||
554 | ret = snd_pcm_hw_rule_add(substream->runtime, 0, | ||
555 | SNDRV_PCM_HW_PARAM_CHANNELS, | ||
556 | aaci_rule_channels, aaci, | ||
557 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | ||
558 | if (ret) | ||
559 | return ret; | ||
560 | |||
561 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
562 | ret = __aaci_pcm_open(aaci, substream, &aaci->playback); | ||
563 | } else { | ||
564 | ret = __aaci_pcm_open(aaci, substream, &aaci->capture); | ||
565 | } | ||
566 | return ret; | ||
567 | } | ||
568 | |||
569 | static int aaci_pcm_playback_hw_params(struct snd_pcm_substream *substream, | ||
570 | struct snd_pcm_hw_params *params) | ||
571 | { | ||
572 | struct aaci_runtime *aacirun = substream->runtime->private_data; | ||
573 | unsigned int channels = params_channels(params); | ||
574 | int ret; | ||
575 | |||
576 | WARN_ON(channels >= ARRAY_SIZE(channels_to_txmask) || | ||
577 | !channels_to_txmask[channels]); | ||
578 | |||
579 | ret = aaci_pcm_hw_params(substream, aacirun, params); | ||
580 | |||
581 | /* | ||
582 | * Enable FIFO, compact mode, 16 bits per sample. | ||
583 | * FIXME: double rate slots? | ||
584 | */ | ||
585 | if (ret >= 0) | ||
586 | aacirun->cr |= channels_to_txmask[channels]; | ||
587 | |||
588 | return ret; | ||
589 | } | ||
590 | |||
591 | static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun) | 573 | static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun) |
592 | { | 574 | { |
593 | u32 ie; | 575 | u32 ie; |
@@ -657,27 +639,13 @@ static struct snd_pcm_ops aaci_playback_ops = { | |||
657 | .open = aaci_pcm_open, | 639 | .open = aaci_pcm_open, |
658 | .close = aaci_pcm_close, | 640 | .close = aaci_pcm_close, |
659 | .ioctl = snd_pcm_lib_ioctl, | 641 | .ioctl = snd_pcm_lib_ioctl, |
660 | .hw_params = aaci_pcm_playback_hw_params, | 642 | .hw_params = aaci_pcm_hw_params, |
661 | .hw_free = aaci_pcm_hw_free, | 643 | .hw_free = aaci_pcm_hw_free, |
662 | .prepare = aaci_pcm_prepare, | 644 | .prepare = aaci_pcm_prepare, |
663 | .trigger = aaci_pcm_playback_trigger, | 645 | .trigger = aaci_pcm_playback_trigger, |
664 | .pointer = aaci_pcm_pointer, | 646 | .pointer = aaci_pcm_pointer, |
665 | }; | 647 | }; |
666 | 648 | ||
667 | static int aaci_pcm_capture_hw_params(struct snd_pcm_substream *substream, | ||
668 | struct snd_pcm_hw_params *params) | ||
669 | { | ||
670 | struct aaci_runtime *aacirun = substream->runtime->private_data; | ||
671 | int ret; | ||
672 | |||
673 | ret = aaci_pcm_hw_params(substream, aacirun, params); | ||
674 | if (ret >= 0) | ||
675 | /* Line in record: slot 3 and 4 */ | ||
676 | aacirun->cr |= CR_SL3 | CR_SL4; | ||
677 | |||
678 | return ret; | ||
679 | } | ||
680 | |||
681 | static void aaci_pcm_capture_stop(struct aaci_runtime *aacirun) | 649 | static void aaci_pcm_capture_stop(struct aaci_runtime *aacirun) |
682 | { | 650 | { |
683 | u32 ie; | 651 | u32 ie; |
@@ -774,7 +742,7 @@ static struct snd_pcm_ops aaci_capture_ops = { | |||
774 | .open = aaci_pcm_open, | 742 | .open = aaci_pcm_open, |
775 | .close = aaci_pcm_close, | 743 | .close = aaci_pcm_close, |
776 | .ioctl = snd_pcm_lib_ioctl, | 744 | .ioctl = snd_pcm_lib_ioctl, |
777 | .hw_params = aaci_pcm_capture_hw_params, | 745 | .hw_params = aaci_pcm_hw_params, |
778 | .hw_free = aaci_pcm_hw_free, | 746 | .hw_free = aaci_pcm_hw_free, |
779 | .prepare = aaci_pcm_capture_prepare, | 747 | .prepare = aaci_pcm_capture_prepare, |
780 | .trigger = aaci_pcm_capture_trigger, | 748 | .trigger = aaci_pcm_capture_trigger, |
@@ -941,12 +909,13 @@ static struct aaci * __devinit aaci_init_card(struct amba_device *dev) | |||
941 | strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver)); | 909 | strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver)); |
942 | strlcpy(card->shortname, "ARM AC'97 Interface", sizeof(card->shortname)); | 910 | strlcpy(card->shortname, "ARM AC'97 Interface", sizeof(card->shortname)); |
943 | snprintf(card->longname, sizeof(card->longname), | 911 | snprintf(card->longname, sizeof(card->longname), |
944 | "%s at 0x%016llx, irq %d", | 912 | "%s PL%03x rev%u at 0x%08llx, irq %d", |
945 | card->shortname, (unsigned long long)dev->res.start, | 913 | card->shortname, amba_part(dev), amba_rev(dev), |
946 | dev->irq[0]); | 914 | (unsigned long long)dev->res.start, dev->irq[0]); |
947 | 915 | ||
948 | aaci = card->private_data; | 916 | aaci = card->private_data; |
949 | mutex_init(&aaci->ac97_sem); | 917 | mutex_init(&aaci->ac97_sem); |
918 | mutex_init(&aaci->irq_lock); | ||
950 | aaci->card = card; | 919 | aaci->card = card; |
951 | aaci->dev = dev; | 920 | aaci->dev = dev; |
952 | 921 | ||
@@ -984,6 +953,10 @@ static unsigned int __devinit aaci_size_fifo(struct aaci *aaci) | |||
984 | struct aaci_runtime *aacirun = &aaci->playback; | 953 | struct aaci_runtime *aacirun = &aaci->playback; |
985 | int i; | 954 | int i; |
986 | 955 | ||
956 | /* | ||
957 | * Enable the channel, but don't assign it to any slots, so | ||
958 | * it won't empty onto the AC'97 link. | ||
959 | */ | ||
987 | writel(CR_FEN | CR_SZ16 | CR_EN, aacirun->base + AACI_TXCR); | 960 | writel(CR_FEN | CR_SZ16 | CR_EN, aacirun->base + AACI_TXCR); |
988 | 961 | ||
989 | for (i = 0; !(readl(aacirun->base + AACI_SR) & SR_TXFF) && i < 4096; i++) | 962 | for (i = 0; !(readl(aacirun->base + AACI_SR) & SR_TXFF) && i < 4096; i++) |
@@ -1002,7 +975,7 @@ static unsigned int __devinit aaci_size_fifo(struct aaci *aaci) | |||
1002 | writel(aaci->maincr, aaci->base + AACI_MAINCR); | 975 | writel(aaci->maincr, aaci->base + AACI_MAINCR); |
1003 | 976 | ||
1004 | /* | 977 | /* |
1005 | * If we hit 4096, we failed. Go back to the specified | 978 | * If we hit 4096 entries, we failed. Go back to the specified |
1006 | * fifo depth. | 979 | * fifo depth. |
1007 | */ | 980 | */ |
1008 | if (i == 4096) | 981 | if (i == 4096) |
@@ -1011,7 +984,8 @@ static unsigned int __devinit aaci_size_fifo(struct aaci *aaci) | |||
1011 | return i; | 984 | return i; |
1012 | } | 985 | } |
1013 | 986 | ||
1014 | static int __devinit aaci_probe(struct amba_device *dev, struct amba_id *id) | 987 | static int __devinit aaci_probe(struct amba_device *dev, |
988 | const struct amba_id *id) | ||
1015 | { | 989 | { |
1016 | struct aaci *aaci; | 990 | struct aaci *aaci; |
1017 | int ret, i; | 991 | int ret, i; |
@@ -1067,11 +1041,12 @@ static int __devinit aaci_probe(struct amba_device *dev, struct amba_id *id) | |||
1067 | 1041 | ||
1068 | /* | 1042 | /* |
1069 | * Size the FIFOs (must be multiple of 16). | 1043 | * Size the FIFOs (must be multiple of 16). |
1044 | * This is the number of entries in the FIFO. | ||
1070 | */ | 1045 | */ |
1071 | aaci->fifosize = aaci_size_fifo(aaci); | 1046 | aaci->fifo_depth = aaci_size_fifo(aaci); |
1072 | if (aaci->fifosize & 15) { | 1047 | if (aaci->fifo_depth & 15) { |
1073 | printk(KERN_WARNING "AACI: fifosize = %d not supported\n", | 1048 | printk(KERN_WARNING "AACI: FIFO depth %d not supported\n", |
1074 | aaci->fifosize); | 1049 | aaci->fifo_depth); |
1075 | ret = -ENODEV; | 1050 | ret = -ENODEV; |
1076 | goto out; | 1051 | goto out; |
1077 | } | 1052 | } |
@@ -1084,8 +1059,8 @@ static int __devinit aaci_probe(struct amba_device *dev, struct amba_id *id) | |||
1084 | 1059 | ||
1085 | ret = snd_card_register(aaci->card); | 1060 | ret = snd_card_register(aaci->card); |
1086 | if (ret == 0) { | 1061 | if (ret == 0) { |
1087 | dev_info(&dev->dev, "%s, fifo %d\n", aaci->card->longname, | 1062 | dev_info(&dev->dev, "%s\n", aaci->card->longname); |
1088 | aaci->fifosize); | 1063 | dev_info(&dev->dev, "FIFO %u entries\n", aaci->fifo_depth); |
1089 | amba_set_drvdata(dev, aaci->card); | 1064 | amba_set_drvdata(dev, aaci->card); |
1090 | return ret; | 1065 | return ret; |
1091 | } | 1066 | } |
diff --git a/sound/arm/aaci.h b/sound/arm/aaci.h index 6a4a2eebdda1..5791bd5bd2ab 100644 --- a/sound/arm/aaci.h +++ b/sound/arm/aaci.h | |||
@@ -210,6 +210,8 @@ struct aaci_runtime { | |||
210 | u32 cr; | 210 | u32 cr; |
211 | struct snd_pcm_substream *substream; | 211 | struct snd_pcm_substream *substream; |
212 | 212 | ||
213 | unsigned int period; /* byte size of a "period" */ | ||
214 | |||
213 | /* | 215 | /* |
214 | * PIO support | 216 | * PIO support |
215 | */ | 217 | */ |
@@ -217,15 +219,16 @@ struct aaci_runtime { | |||
217 | void *end; | 219 | void *end; |
218 | void *ptr; | 220 | void *ptr; |
219 | int bytes; | 221 | int bytes; |
220 | unsigned int period; | 222 | unsigned int fifo_bytes; |
221 | unsigned int fifosz; | ||
222 | }; | 223 | }; |
223 | 224 | ||
224 | struct aaci { | 225 | struct aaci { |
225 | struct amba_device *dev; | 226 | struct amba_device *dev; |
226 | struct snd_card *card; | 227 | struct snd_card *card; |
227 | void __iomem *base; | 228 | void __iomem *base; |
228 | unsigned int fifosize; | 229 | unsigned int fifo_depth; |
230 | unsigned int users; | ||
231 | struct mutex irq_lock; | ||
229 | 232 | ||
230 | /* AC'97 */ | 233 | /* AC'97 */ |
231 | struct mutex ac97_sem; | 234 | struct mutex ac97_sem; |