aboutsummaryrefslogtreecommitdiffstats
path: root/sound/firewire
diff options
context:
space:
mode:
Diffstat (limited to 'sound/firewire')
-rw-r--r--sound/firewire/dice.c137
1 files changed, 102 insertions, 35 deletions
diff --git a/sound/firewire/dice.c b/sound/firewire/dice.c
index e6bba6d32bd8..61dd00c4fae3 100644
--- a/sound/firewire/dice.c
+++ b/sound/firewire/dice.c
@@ -70,6 +70,17 @@ static const unsigned int dice_rates[] = {
70 [6] = 192000, 70 [6] = 192000,
71}; 71};
72 72
73static unsigned int rate_to_index(unsigned int rate)
74{
75 unsigned int i;
76
77 for (i = 0; i < ARRAY_SIZE(dice_rates); ++i)
78 if (dice_rates[i] == rate)
79 return i;
80
81 return 0;
82}
83
73static unsigned int rate_index_to_mode(unsigned int rate_index) 84static unsigned int rate_index_to_mode(unsigned int rate_index)
74{ 85{
75 return ((int)rate_index - 1) / 2; 86 return ((int)rate_index - 1) / 2;
@@ -302,6 +313,59 @@ static void dice_notification(struct fw_card *card, struct fw_request *request,
302 wake_up(&dice->hwdep_wait); 313 wake_up(&dice->hwdep_wait);
303} 314}
304 315
316static int dice_rate_constraint(struct snd_pcm_hw_params *params,
317 struct snd_pcm_hw_rule *rule)
318{
319 struct dice *dice = rule->private;
320 const struct snd_interval *channels =
321 hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
322 struct snd_interval *rate =
323 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
324 struct snd_interval allowed_rates = {
325 .min = UINT_MAX, .max = 0, .integer = 1
326 };
327 unsigned int i, mode;
328
329 for (i = 0; i < ARRAY_SIZE(dice_rates); ++i) {
330 mode = rate_index_to_mode(i);
331 if ((dice->clock_caps & (1 << i)) &&
332 snd_interval_test(channels, dice->rx_channels[mode])) {
333 allowed_rates.min = min(allowed_rates.min,
334 dice_rates[i]);
335 allowed_rates.max = max(allowed_rates.max,
336 dice_rates[i]);
337 }
338 }
339
340 return snd_interval_refine(rate, &allowed_rates);
341}
342
343static int dice_channels_constraint(struct snd_pcm_hw_params *params,
344 struct snd_pcm_hw_rule *rule)
345{
346 struct dice *dice = rule->private;
347 const struct snd_interval *rate =
348 hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
349 struct snd_interval *channels =
350 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
351 struct snd_interval allowed_channels = {
352 .min = UINT_MAX, .max = 0, .integer = 1
353 };
354 unsigned int i, mode;
355
356 for (i = 0; i < ARRAY_SIZE(dice_rates); ++i)
357 if ((dice->clock_caps & (1 << i)) &&
358 snd_interval_test(rate, dice_rates[i])) {
359 mode = rate_index_to_mode(i);
360 allowed_channels.min = min(allowed_channels.min,
361 dice->rx_channels[mode]);
362 allowed_channels.max = max(allowed_channels.max,
363 dice->rx_channels[mode]);
364 }
365
366 return snd_interval_refine(channels, &allowed_channels);
367}
368
305static int dice_open(struct snd_pcm_substream *substream) 369static int dice_open(struct snd_pcm_substream *substream)
306{ 370{
307 static const struct snd_pcm_hardware hardware = { 371 static const struct snd_pcm_hardware hardware = {
@@ -311,6 +375,8 @@ static int dice_open(struct snd_pcm_substream *substream)
311 SNDRV_PCM_INFO_INTERLEAVED | 375 SNDRV_PCM_INFO_INTERLEAVED |
312 SNDRV_PCM_INFO_BLOCK_TRANSFER, 376 SNDRV_PCM_INFO_BLOCK_TRANSFER,
313 .formats = AMDTP_OUT_PCM_FORMAT_BITS, 377 .formats = AMDTP_OUT_PCM_FORMAT_BITS,
378 .channels_min = UINT_MAX,
379 .channels_max = 0,
314 .buffer_bytes_max = 16 * 1024 * 1024, 380 .buffer_bytes_max = 16 * 1024 * 1024,
315 .period_bytes_min = 1, 381 .period_bytes_min = 1,
316 .period_bytes_max = UINT_MAX, 382 .period_bytes_max = UINT_MAX,
@@ -319,53 +385,46 @@ static int dice_open(struct snd_pcm_substream *substream)
319 }; 385 };
320 struct dice *dice = substream->private_data; 386 struct dice *dice = substream->private_data;
321 struct snd_pcm_runtime *runtime = substream->runtime; 387 struct snd_pcm_runtime *runtime = substream->runtime;
322 __be32 clock_sel, data[2]; 388 unsigned int i;
323 unsigned int rate_index, number_audio, number_midi;
324 int err; 389 int err;
325 390
326 err = dice_try_lock(dice); 391 err = dice_try_lock(dice);
327 if (err < 0) 392 if (err < 0)
328 goto error; 393 goto error;
329 394
330 err = snd_fw_transaction(dice->unit, TCODE_READ_QUADLET_REQUEST,
331 global_address(dice, GLOBAL_CLOCK_SELECT),
332 &clock_sel, 4, 0);
333 if (err < 0)
334 goto err_lock;
335 rate_index = (be32_to_cpu(clock_sel) & CLOCK_RATE_MASK)
336 >> CLOCK_RATE_SHIFT;
337 if (rate_index >= ARRAY_SIZE(dice_rates)) {
338 err = -ENXIO;
339 goto err_lock;
340 }
341
342 err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST,
343 rx_address(dice, RX_NUMBER_AUDIO),
344 data, 2 * 4, 0);
345 if (err < 0)
346 goto err_lock;
347 number_audio = be32_to_cpu(data[0]);
348 number_midi = be32_to_cpu(data[1]);
349
350 runtime->hw = hardware; 395 runtime->hw = hardware;
351 396
352 runtime->hw.rates = snd_pcm_rate_to_rate_bit(dice_rates[rate_index]); 397 for (i = 0; i < ARRAY_SIZE(dice_rates); ++i)
398 if (dice->clock_caps & (1 << i))
399 runtime->hw.rates |=
400 snd_pcm_rate_to_rate_bit(dice_rates[i]);
353 snd_pcm_limit_hw_rates(runtime); 401 snd_pcm_limit_hw_rates(runtime);
354 402
355 runtime->hw.channels_min = number_audio; 403 for (i = 0; i < 3; ++i)
356 runtime->hw.channels_max = number_audio; 404 if (dice->rx_channels[i]) {
405 runtime->hw.channels_min = min(runtime->hw.channels_min,
406 dice->rx_channels[i]);
407 runtime->hw.channels_max = max(runtime->hw.channels_max,
408 dice->rx_channels[i]);
409 }
357 410
358 amdtp_out_stream_set_parameters(&dice->stream, dice_rates[rate_index], 411 err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
359 number_audio, number_midi); 412 dice_rate_constraint, dice,
413 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
414 if (err < 0)
415 goto err_lock;
416 err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
417 dice_channels_constraint, dice,
418 SNDRV_PCM_HW_PARAM_RATE, -1);
419 if (err < 0)
420 goto err_lock;
360 421
361 err = snd_pcm_hw_constraint_step(runtime, 0, 422 err = snd_pcm_hw_constraint_step(runtime, 0,
362 SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 423 SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 32);
363 amdtp_syt_intervals[rate_index]);
364 if (err < 0) 424 if (err < 0)
365 goto err_lock; 425 goto err_lock;
366 err = snd_pcm_hw_constraint_step(runtime, 0, 426 err = snd_pcm_hw_constraint_step(runtime, 0,
367 SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 427 SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 32);
368 amdtp_syt_intervals[rate_index]);
369 if (err < 0) 428 if (err < 0)
370 goto err_lock; 429 goto err_lock;
371 430
@@ -502,6 +561,7 @@ static int dice_hw_params(struct snd_pcm_substream *substream,
502 struct snd_pcm_hw_params *hw_params) 561 struct snd_pcm_hw_params *hw_params)
503{ 562{
504 struct dice *dice = substream->private_data; 563 struct dice *dice = substream->private_data;
564 unsigned int rate_index, mode;
505 int err; 565 int err;
506 566
507 mutex_lock(&dice->mutex); 567 mutex_lock(&dice->mutex);
@@ -511,15 +571,22 @@ static int dice_hw_params(struct snd_pcm_substream *substream,
511 err = snd_pcm_lib_alloc_vmalloc_buffer(substream, 571 err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
512 params_buffer_bytes(hw_params)); 572 params_buffer_bytes(hw_params));
513 if (err < 0) 573 if (err < 0)
514 goto error; 574 return err;
515 575
576 rate_index = rate_to_index(params_rate(hw_params));
577 err = dice_change_rate(dice, rate_index << CLOCK_RATE_SHIFT);
578 if (err < 0)
579 return err;
580
581 mode = rate_index_to_mode(rate_index);
582 amdtp_out_stream_set_parameters(&dice->stream,
583 params_rate(hw_params),
584 params_channels(hw_params),
585 dice->rx_midi_ports[mode]);
516 amdtp_out_stream_set_pcm_format(&dice->stream, 586 amdtp_out_stream_set_pcm_format(&dice->stream,
517 params_format(hw_params)); 587 params_format(hw_params));
518 588
519 return 0; 589 return 0;
520
521error:
522 return err;
523} 590}
524 591
525static int dice_hw_free(struct snd_pcm_substream *substream) 592static int dice_hw_free(struct snd_pcm_substream *substream)