Loading sound/firewire/dice.c +102 −35 Original line number Diff line number Diff line Loading @@ -70,6 +70,17 @@ static const unsigned int dice_rates[] = { [6] = 192000, }; static unsigned int rate_to_index(unsigned int rate) { unsigned int i; for (i = 0; i < ARRAY_SIZE(dice_rates); ++i) if (dice_rates[i] == rate) return i; return 0; } static unsigned int rate_index_to_mode(unsigned int rate_index) { return ((int)rate_index - 1) / 2; Loading Loading @@ -302,6 +313,59 @@ static void dice_notification(struct fw_card *card, struct fw_request *request, wake_up(&dice->hwdep_wait); } static int dice_rate_constraint(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { struct dice *dice = rule->private; const struct snd_interval *channels = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS); struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); struct snd_interval allowed_rates = { .min = UINT_MAX, .max = 0, .integer = 1 }; unsigned int i, mode; for (i = 0; i < ARRAY_SIZE(dice_rates); ++i) { mode = rate_index_to_mode(i); if ((dice->clock_caps & (1 << i)) && snd_interval_test(channels, dice->rx_channels[mode])) { allowed_rates.min = min(allowed_rates.min, dice_rates[i]); allowed_rates.max = max(allowed_rates.max, dice_rates[i]); } } return snd_interval_refine(rate, &allowed_rates); } static int dice_channels_constraint(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { struct dice *dice = rule->private; const struct snd_interval *rate = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE); struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); struct snd_interval allowed_channels = { .min = UINT_MAX, .max = 0, .integer = 1 }; unsigned int i, mode; for (i = 0; i < ARRAY_SIZE(dice_rates); ++i) if ((dice->clock_caps & (1 << i)) && snd_interval_test(rate, dice_rates[i])) { mode = rate_index_to_mode(i); allowed_channels.min = min(allowed_channels.min, dice->rx_channels[mode]); allowed_channels.max = max(allowed_channels.max, dice->rx_channels[mode]); } return snd_interval_refine(channels, &allowed_channels); } static int dice_open(struct snd_pcm_substream *substream) { static const struct snd_pcm_hardware hardware = { Loading @@ -311,6 +375,8 @@ static int dice_open(struct snd_pcm_substream *substream) SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER, .formats = AMDTP_OUT_PCM_FORMAT_BITS, .channels_min = UINT_MAX, .channels_max = 0, .buffer_bytes_max = 16 * 1024 * 1024, .period_bytes_min = 1, .period_bytes_max = UINT_MAX, Loading @@ -319,53 +385,46 @@ static int dice_open(struct snd_pcm_substream *substream) }; struct dice *dice = substream->private_data; struct snd_pcm_runtime *runtime = substream->runtime; __be32 clock_sel, data[2]; unsigned int rate_index, number_audio, number_midi; unsigned int i; int err; err = dice_try_lock(dice); if (err < 0) goto error; err = snd_fw_transaction(dice->unit, TCODE_READ_QUADLET_REQUEST, global_address(dice, GLOBAL_CLOCK_SELECT), &clock_sel, 4, 0); if (err < 0) goto err_lock; rate_index = (be32_to_cpu(clock_sel) & CLOCK_RATE_MASK) >> CLOCK_RATE_SHIFT; if (rate_index >= ARRAY_SIZE(dice_rates)) { err = -ENXIO; goto err_lock; } err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST, rx_address(dice, RX_NUMBER_AUDIO), data, 2 * 4, 0); if (err < 0) goto err_lock; number_audio = be32_to_cpu(data[0]); number_midi = be32_to_cpu(data[1]); runtime->hw = hardware; runtime->hw.rates = snd_pcm_rate_to_rate_bit(dice_rates[rate_index]); for (i = 0; i < ARRAY_SIZE(dice_rates); ++i) if (dice->clock_caps & (1 << i)) runtime->hw.rates |= snd_pcm_rate_to_rate_bit(dice_rates[i]); snd_pcm_limit_hw_rates(runtime); runtime->hw.channels_min = number_audio; runtime->hw.channels_max = number_audio; for (i = 0; i < 3; ++i) if (dice->rx_channels[i]) { runtime->hw.channels_min = min(runtime->hw.channels_min, dice->rx_channels[i]); runtime->hw.channels_max = max(runtime->hw.channels_max, dice->rx_channels[i]); } amdtp_out_stream_set_parameters(&dice->stream, dice_rates[rate_index], number_audio, number_midi); err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, dice_rate_constraint, dice, SNDRV_PCM_HW_PARAM_CHANNELS, -1); if (err < 0) goto err_lock; err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, dice_channels_constraint, dice, SNDRV_PCM_HW_PARAM_RATE, -1); if (err < 0) goto err_lock; err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, amdtp_syt_intervals[rate_index]); SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 32); if (err < 0) goto err_lock; err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, amdtp_syt_intervals[rate_index]); SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 32); if (err < 0) goto err_lock; Loading Loading @@ -502,6 +561,7 @@ static int dice_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct dice *dice = substream->private_data; unsigned int rate_index, mode; int err; mutex_lock(&dice->mutex); Loading @@ -511,15 +571,22 @@ static int dice_hw_params(struct snd_pcm_substream *substream, err = snd_pcm_lib_alloc_vmalloc_buffer(substream, params_buffer_bytes(hw_params)); if (err < 0) goto error; return err; rate_index = rate_to_index(params_rate(hw_params)); err = dice_change_rate(dice, rate_index << CLOCK_RATE_SHIFT); if (err < 0) return err; mode = rate_index_to_mode(rate_index); amdtp_out_stream_set_parameters(&dice->stream, params_rate(hw_params), params_channels(hw_params), dice->rx_midi_ports[mode]); amdtp_out_stream_set_pcm_format(&dice->stream, params_format(hw_params)); return 0; error: return err; } static int dice_hw_free(struct snd_pcm_substream *substream) Loading Loading
sound/firewire/dice.c +102 −35 Original line number Diff line number Diff line Loading @@ -70,6 +70,17 @@ static const unsigned int dice_rates[] = { [6] = 192000, }; static unsigned int rate_to_index(unsigned int rate) { unsigned int i; for (i = 0; i < ARRAY_SIZE(dice_rates); ++i) if (dice_rates[i] == rate) return i; return 0; } static unsigned int rate_index_to_mode(unsigned int rate_index) { return ((int)rate_index - 1) / 2; Loading Loading @@ -302,6 +313,59 @@ static void dice_notification(struct fw_card *card, struct fw_request *request, wake_up(&dice->hwdep_wait); } static int dice_rate_constraint(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { struct dice *dice = rule->private; const struct snd_interval *channels = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS); struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); struct snd_interval allowed_rates = { .min = UINT_MAX, .max = 0, .integer = 1 }; unsigned int i, mode; for (i = 0; i < ARRAY_SIZE(dice_rates); ++i) { mode = rate_index_to_mode(i); if ((dice->clock_caps & (1 << i)) && snd_interval_test(channels, dice->rx_channels[mode])) { allowed_rates.min = min(allowed_rates.min, dice_rates[i]); allowed_rates.max = max(allowed_rates.max, dice_rates[i]); } } return snd_interval_refine(rate, &allowed_rates); } static int dice_channels_constraint(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { struct dice *dice = rule->private; const struct snd_interval *rate = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE); struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); struct snd_interval allowed_channels = { .min = UINT_MAX, .max = 0, .integer = 1 }; unsigned int i, mode; for (i = 0; i < ARRAY_SIZE(dice_rates); ++i) if ((dice->clock_caps & (1 << i)) && snd_interval_test(rate, dice_rates[i])) { mode = rate_index_to_mode(i); allowed_channels.min = min(allowed_channels.min, dice->rx_channels[mode]); allowed_channels.max = max(allowed_channels.max, dice->rx_channels[mode]); } return snd_interval_refine(channels, &allowed_channels); } static int dice_open(struct snd_pcm_substream *substream) { static const struct snd_pcm_hardware hardware = { Loading @@ -311,6 +375,8 @@ static int dice_open(struct snd_pcm_substream *substream) SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER, .formats = AMDTP_OUT_PCM_FORMAT_BITS, .channels_min = UINT_MAX, .channels_max = 0, .buffer_bytes_max = 16 * 1024 * 1024, .period_bytes_min = 1, .period_bytes_max = UINT_MAX, Loading @@ -319,53 +385,46 @@ static int dice_open(struct snd_pcm_substream *substream) }; struct dice *dice = substream->private_data; struct snd_pcm_runtime *runtime = substream->runtime; __be32 clock_sel, data[2]; unsigned int rate_index, number_audio, number_midi; unsigned int i; int err; err = dice_try_lock(dice); if (err < 0) goto error; err = snd_fw_transaction(dice->unit, TCODE_READ_QUADLET_REQUEST, global_address(dice, GLOBAL_CLOCK_SELECT), &clock_sel, 4, 0); if (err < 0) goto err_lock; rate_index = (be32_to_cpu(clock_sel) & CLOCK_RATE_MASK) >> CLOCK_RATE_SHIFT; if (rate_index >= ARRAY_SIZE(dice_rates)) { err = -ENXIO; goto err_lock; } err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST, rx_address(dice, RX_NUMBER_AUDIO), data, 2 * 4, 0); if (err < 0) goto err_lock; number_audio = be32_to_cpu(data[0]); number_midi = be32_to_cpu(data[1]); runtime->hw = hardware; runtime->hw.rates = snd_pcm_rate_to_rate_bit(dice_rates[rate_index]); for (i = 0; i < ARRAY_SIZE(dice_rates); ++i) if (dice->clock_caps & (1 << i)) runtime->hw.rates |= snd_pcm_rate_to_rate_bit(dice_rates[i]); snd_pcm_limit_hw_rates(runtime); runtime->hw.channels_min = number_audio; runtime->hw.channels_max = number_audio; for (i = 0; i < 3; ++i) if (dice->rx_channels[i]) { runtime->hw.channels_min = min(runtime->hw.channels_min, dice->rx_channels[i]); runtime->hw.channels_max = max(runtime->hw.channels_max, dice->rx_channels[i]); } amdtp_out_stream_set_parameters(&dice->stream, dice_rates[rate_index], number_audio, number_midi); err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, dice_rate_constraint, dice, SNDRV_PCM_HW_PARAM_CHANNELS, -1); if (err < 0) goto err_lock; err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, dice_channels_constraint, dice, SNDRV_PCM_HW_PARAM_RATE, -1); if (err < 0) goto err_lock; err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, amdtp_syt_intervals[rate_index]); SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 32); if (err < 0) goto err_lock; err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, amdtp_syt_intervals[rate_index]); SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 32); if (err < 0) goto err_lock; Loading Loading @@ -502,6 +561,7 @@ static int dice_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct dice *dice = substream->private_data; unsigned int rate_index, mode; int err; mutex_lock(&dice->mutex); Loading @@ -511,15 +571,22 @@ static int dice_hw_params(struct snd_pcm_substream *substream, err = snd_pcm_lib_alloc_vmalloc_buffer(substream, params_buffer_bytes(hw_params)); if (err < 0) goto error; return err; rate_index = rate_to_index(params_rate(hw_params)); err = dice_change_rate(dice, rate_index << CLOCK_RATE_SHIFT); if (err < 0) return err; mode = rate_index_to_mode(rate_index); amdtp_out_stream_set_parameters(&dice->stream, params_rate(hw_params), params_channels(hw_params), dice->rx_midi_ports[mode]); amdtp_out_stream_set_pcm_format(&dice->stream, params_format(hw_params)); return 0; error: return err; } static int dice_hw_free(struct snd_pcm_substream *substream) Loading