aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2011-01-13 05:13:17 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2011-01-25 16:20:23 -0500
commite831d80b453a3586f1e1664a705c153a4ced39b8 (patch)
tree7c6a48a62f299e8bdca946490571b176658831ac
parentb60fb519d7977e606621af85585c3677fc290ef8 (diff)
ALSA: AACI: fix number of channels for record
AC'97 codecs only support two channels for recording, so we shouldn't advertize that there are up to six channels available. Limit the selection of 4 and 6 channel audio to playback only. As this adds additional SNDRV_PCM_STREAM_PLAYBACK conditionals, we can combine some resulting in the elimination of __aaci_pcm_open() entirely, and making the code easier to read. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--sound/arm/aaci.c114
1 files changed, 52 insertions, 62 deletions
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
index 65685afd8f77..ab66d462d865 100644
--- a/sound/arm/aaci.c
+++ b/sound/arm/aaci.c
@@ -357,7 +357,7 @@ static struct snd_pcm_hardware aaci_hw_info = {
357 357
358 /* rates are setup from the AC'97 codec */ 358 /* rates are setup from the AC'97 codec */
359 .channels_min = 2, 359 .channels_min = 2,
360 .channels_max = 6, 360 .channels_max = 2,
361 .buffer_bytes_max = 64 * 1024, 361 .buffer_bytes_max = 64 * 1024,
362 .period_bytes_min = 256, 362 .period_bytes_min = 256,
363 .period_bytes_max = PAGE_SIZE, 363 .period_bytes_max = PAGE_SIZE,
@@ -365,22 +365,67 @@ static struct snd_pcm_hardware aaci_hw_info = {
365 .periods_max = PAGE_SIZE / 16, 365 .periods_max = PAGE_SIZE / 16,
366}; 366};
367 367
368static int __aaci_pcm_open(struct aaci *aaci, 368/*
369 struct snd_pcm_substream *substream, 369 * We can support two and four channel audio. Unfortunately
370 struct aaci_runtime *aacirun) 370 * six channel audio requires a non-standard channel ordering:
371 * 2 -> FL(3), FR(4)
372 * 4 -> FL(3), FR(4), SL(7), SR(8)
373 * 6 -> FL(3), FR(4), SL(7), SR(8), C(6), LFE(9) (required)
374 * FL(3), FR(4), C(6), SL(7), SR(8), LFE(9) (actual)
375 * This requires an ALSA configuration file to correct.
376 */
377static int aaci_rule_channels(struct snd_pcm_hw_params *p,
378 struct snd_pcm_hw_rule *rule)
379{
380 static unsigned int channel_list[] = { 2, 4, 6 };
381 struct aaci *aaci = rule->private;
382 unsigned int mask = 1 << 0, slots;
383
384 /* pcms[0] is the our 5.1 PCM instance. */
385 slots = aaci->ac97_bus->pcms[0].r[0].slots;
386 if (slots & (1 << AC97_SLOT_PCM_SLEFT)) {
387 mask |= 1 << 1;
388 if (slots & (1 << AC97_SLOT_LFE))
389 mask |= 1 << 2;
390 }
391
392 return snd_interval_list(hw_param_interval(p, rule->var),
393 ARRAY_SIZE(channel_list), channel_list, mask);
394}
395
396static int aaci_pcm_open(struct snd_pcm_substream *substream)
371{ 397{
372 struct snd_pcm_runtime *runtime = substream->runtime; 398 struct snd_pcm_runtime *runtime = substream->runtime;
399 struct aaci *aaci = substream->private_data;
400 struct aaci_runtime *aacirun;
373 int ret = 0; 401 int ret = 0;
374 402
403 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
404 aacirun = &aaci->playback;
405 } else {
406 aacirun = &aaci->capture;
407 }
408
375 aacirun->substream = substream; 409 aacirun->substream = substream;
376 runtime->private_data = aacirun; 410 runtime->private_data = aacirun;
377 runtime->hw = aaci_hw_info; 411 runtime->hw = aaci_hw_info;
378 runtime->hw.rates = aacirun->pcm->rates; 412 runtime->hw.rates = aacirun->pcm->rates;
379 snd_pcm_limit_hw_rates(runtime); 413 snd_pcm_limit_hw_rates(runtime);
380 414
381 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && 415 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
382 aacirun->pcm->r[1].slots) 416 runtime->hw.channels_max = 6;
383 snd_ac97_pcm_double_rate_rules(runtime); 417
418 /* Add rule describing channel dependency. */
419 ret = snd_pcm_hw_rule_add(substream->runtime, 0,
420 SNDRV_PCM_HW_PARAM_CHANNELS,
421 aaci_rule_channels, aaci,
422 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
423 if (ret)
424 return ret;
425
426 if (aacirun->pcm->r[1].slots)
427 snd_ac97_pcm_double_rate_rules(runtime);
428 }
384 429
385 /* 430 /*
386 * FIXME: ALSA specifies fifo_size in bytes. If we're in normal 431 * FIXME: ALSA specifies fifo_size in bytes. If we're in normal
@@ -512,61 +557,6 @@ static const u32 channels_to_txmask[] = {
512 [6] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8 | CR_SL6 | CR_SL9, 557 [6] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8 | CR_SL6 | CR_SL9,
513}; 558};
514 559
515/*
516 * We can support two and four channel audio. Unfortunately
517 * six channel audio requires a non-standard channel ordering:
518 * 2 -> FL(3), FR(4)
519 * 4 -> FL(3), FR(4), SL(7), SR(8)
520 * 6 -> FL(3), FR(4), SL(7), SR(8), C(6), LFE(9) (required)
521 * FL(3), FR(4), C(6), SL(7), SR(8), LFE(9) (actual)
522 * This requires an ALSA configuration file to correct.
523 */
524static unsigned int channel_list[] = { 2, 4, 6 };
525
526static int
527aaci_rule_channels(struct snd_pcm_hw_params *p, struct snd_pcm_hw_rule *rule)
528{
529 struct aaci *aaci = rule->private;
530 unsigned int chan_mask = 1 << 0, slots;
531
532 /*
533 * pcms[0] is the our 5.1 PCM instance.
534 */
535 slots = aaci->ac97_bus->pcms[0].r[0].slots;
536 if (slots & (1 << AC97_SLOT_PCM_SLEFT)) {
537 chan_mask |= 1 << 1;
538 if (slots & (1 << AC97_SLOT_LFE))
539 chan_mask |= 1 << 2;
540 }
541
542 return snd_interval_list(hw_param_interval(p, rule->var),
543 ARRAY_SIZE(channel_list), channel_list,
544 chan_mask);
545}
546
547static int aaci_pcm_open(struct snd_pcm_substream *substream)
548{
549 struct aaci *aaci = substream->private_data;
550 int ret;
551
552 /*
553 * Add rule describing channel dependency.
554 */
555 ret = snd_pcm_hw_rule_add(substream->runtime, 0,
556 SNDRV_PCM_HW_PARAM_CHANNELS,
557 aaci_rule_channels, aaci,
558 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
559 if (ret)
560 return ret;
561
562 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
563 ret = __aaci_pcm_open(aaci, substream, &aaci->playback);
564 } else {
565 ret = __aaci_pcm_open(aaci, substream, &aaci->capture);
566 }
567 return ret;
568}
569
570static int aaci_pcm_playback_hw_params(struct snd_pcm_substream *substream, 560static int aaci_pcm_playback_hw_params(struct snd_pcm_substream *substream,
571 struct snd_pcm_hw_params *params) 561 struct snd_pcm_hw_params *params)
572{ 562{