diff options
Diffstat (limited to 'sound/firewire/dice.c')
-rw-r--r-- | sound/firewire/dice.c | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/sound/firewire/dice.c b/sound/firewire/dice.c index 26b2158f87d1..cd4c6b6d072e 100644 --- a/sound/firewire/dice.c +++ b/sound/firewire/dice.c | |||
@@ -563,7 +563,7 @@ static int dice_hw_params(struct snd_pcm_substream *substream, | |||
563 | struct snd_pcm_hw_params *hw_params) | 563 | struct snd_pcm_hw_params *hw_params) |
564 | { | 564 | { |
565 | struct dice *dice = substream->private_data; | 565 | struct dice *dice = substream->private_data; |
566 | unsigned int rate_index, mode; | 566 | unsigned int rate_index, mode, rate, channels, i; |
567 | int err; | 567 | int err; |
568 | 568 | ||
569 | mutex_lock(&dice->mutex); | 569 | mutex_lock(&dice->mutex); |
@@ -575,15 +575,36 @@ static int dice_hw_params(struct snd_pcm_substream *substream, | |||
575 | if (err < 0) | 575 | if (err < 0) |
576 | return err; | 576 | return err; |
577 | 577 | ||
578 | rate_index = rate_to_index(params_rate(hw_params)); | 578 | rate = params_rate(hw_params); |
579 | rate_index = rate_to_index(rate); | ||
579 | err = dice_change_rate(dice, rate_index << CLOCK_RATE_SHIFT); | 580 | err = dice_change_rate(dice, rate_index << CLOCK_RATE_SHIFT); |
580 | if (err < 0) | 581 | if (err < 0) |
581 | return err; | 582 | return err; |
582 | 583 | ||
584 | /* | ||
585 | * At rates above 96 kHz, pretend that the stream runs at half the | ||
586 | * actual sample rate with twice the number of channels; two samples | ||
587 | * of a channel are stored consecutively in the packet. Requires | ||
588 | * blocking mode and PCM buffer size should be aligned to SYT_INTERVAL. | ||
589 | */ | ||
590 | channels = params_channels(hw_params); | ||
591 | if (rate_index > 4) { | ||
592 | if (channels > AMDTP_MAX_CHANNELS_FOR_PCM / 2) { | ||
593 | err = -ENOSYS; | ||
594 | return err; | ||
595 | } | ||
596 | |||
597 | for (i = 0; i < channels; i++) { | ||
598 | dice->stream.pcm_positions[i * 2] = i; | ||
599 | dice->stream.pcm_positions[i * 2 + 1] = i + channels; | ||
600 | } | ||
601 | |||
602 | rate /= 2; | ||
603 | channels *= 2; | ||
604 | } | ||
605 | |||
583 | mode = rate_index_to_mode(rate_index); | 606 | mode = rate_index_to_mode(rate_index); |
584 | amdtp_stream_set_parameters(&dice->stream, | 607 | amdtp_stream_set_parameters(&dice->stream, rate, channels, |
585 | params_rate(hw_params), | ||
586 | params_channels(hw_params), | ||
587 | dice->rx_midi_ports[mode]); | 608 | dice->rx_midi_ports[mode]); |
588 | amdtp_stream_set_pcm_format(&dice->stream, | 609 | amdtp_stream_set_pcm_format(&dice->stream, |
589 | params_format(hw_params)); | 610 | params_format(hw_params)); |
@@ -1361,7 +1382,7 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) | |||
1361 | dice->resources.channels_mask = 0x00000000ffffffffuLL; | 1382 | dice->resources.channels_mask = 0x00000000ffffffffuLL; |
1362 | 1383 | ||
1363 | err = amdtp_stream_init(&dice->stream, unit, AMDTP_OUT_STREAM, | 1384 | err = amdtp_stream_init(&dice->stream, unit, AMDTP_OUT_STREAM, |
1364 | CIP_BLOCKING | CIP_HI_DUALWIRE); | 1385 | CIP_BLOCKING); |
1365 | if (err < 0) | 1386 | if (err < 0) |
1366 | goto err_resources; | 1387 | goto err_resources; |
1367 | 1388 | ||