diff options
Diffstat (limited to 'sound/firewire/bebob')
-rw-r--r-- | sound/firewire/bebob/bebob.h | 4 | ||||
-rw-r--r-- | sound/firewire/bebob/bebob_midi.c | 2 | ||||
-rw-r--r-- | sound/firewire/bebob/bebob_pcm.c | 71 | ||||
-rw-r--r-- | sound/firewire/bebob/bebob_stream.c | 22 |
4 files changed, 74 insertions, 25 deletions
diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h index 356d6ba60959..d1ad9a8451bc 100644 --- a/sound/firewire/bebob/bebob.h +++ b/sound/firewire/bebob/bebob.h @@ -217,7 +217,9 @@ int snd_bebob_stream_get_clock_src(struct snd_bebob *bebob, enum snd_bebob_clock_type *src); int snd_bebob_stream_discover(struct snd_bebob *bebob); int snd_bebob_stream_init_duplex(struct snd_bebob *bebob); -int snd_bebob_stream_reserve_duplex(struct snd_bebob *bebob, unsigned int rate); +int snd_bebob_stream_reserve_duplex(struct snd_bebob *bebob, unsigned int rate, + unsigned int frames_per_period, + unsigned int frames_per_buffer); int snd_bebob_stream_start_duplex(struct snd_bebob *bebob); void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob); void snd_bebob_stream_destroy_duplex(struct snd_bebob *bebob); diff --git a/sound/firewire/bebob/bebob_midi.c b/sound/firewire/bebob/bebob_midi.c index 4d8805fa8a00..6f597d03e7c1 100644 --- a/sound/firewire/bebob/bebob_midi.c +++ b/sound/firewire/bebob/bebob_midi.c @@ -17,7 +17,7 @@ static int midi_open(struct snd_rawmidi_substream *substream) return err; mutex_lock(&bebob->mutex); - err = snd_bebob_stream_reserve_duplex(bebob, 0); + err = snd_bebob_stream_reserve_duplex(bebob, 0, 0, 0); if (err >= 0) { ++bebob->substreams_counter; err = snd_bebob_stream_start_duplex(bebob); diff --git a/sound/firewire/bebob/bebob_pcm.c b/sound/firewire/bebob/bebob_pcm.c index 0fb9eed46837..1b100159f4c5 100644 --- a/sound/firewire/bebob/bebob_pcm.c +++ b/sound/firewire/bebob/bebob_pcm.c @@ -129,18 +129,17 @@ end: return err; } -static int -pcm_open(struct snd_pcm_substream *substream) +static int pcm_open(struct snd_pcm_substream *substream) { struct snd_bebob *bebob = substream->private_data; const struct snd_bebob_rate_spec *spec = bebob->spec->rate; - unsigned int sampling_rate; + struct amdtp_domain *d = &bebob->domain; enum snd_bebob_clock_type src; int err; err = snd_bebob_stream_lock_try(bebob); if (err < 0) - goto end; + return err; err = pcm_init_hw_params(bebob, substream); if (err < 0) @@ -150,15 +149,20 @@ pcm_open(struct snd_pcm_substream *substream) if (err < 0) goto err_locked; - /* - * When source of clock is internal or any PCM stream are running, - * the available sampling rate is limited at current sampling rate. - */ + mutex_lock(&bebob->mutex); + + // When source of clock is not internal or any stream is reserved for + // transmission of PCM frames, the available sampling rate is limited + // at current one. if (src == SND_BEBOB_CLOCK_TYPE_EXTERNAL || - amdtp_stream_pcm_running(&bebob->tx_stream) || - amdtp_stream_pcm_running(&bebob->rx_stream)) { + (bebob->substreams_counter > 0 && d->events_per_period > 0)) { + unsigned int frames_per_period = d->events_per_period; + unsigned int frames_per_buffer = d->events_per_buffer; + unsigned int sampling_rate; + err = spec->get(bebob, &sampling_rate); if (err < 0) { + mutex_unlock(&bebob->mutex); dev_err(&bebob->unit->device, "fail to get sampling rate: %d\n", err); goto err_locked; @@ -166,11 +170,31 @@ pcm_open(struct snd_pcm_substream *substream) substream->runtime->hw.rate_min = sampling_rate; substream->runtime->hw.rate_max = sampling_rate; + + if (frames_per_period > 0) { + err = snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, + frames_per_period, frames_per_period); + if (err < 0) { + mutex_unlock(&bebob->mutex); + goto err_locked; + } + + err = snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_BUFFER_SIZE, + frames_per_buffer, frames_per_buffer); + if (err < 0) { + mutex_unlock(&bebob->mutex); + goto err_locked; + } + } } + mutex_unlock(&bebob->mutex); + snd_pcm_set_sync(substream); -end: - return err; + + return 0; err_locked: snd_bebob_stream_lock_release(bebob); return err; @@ -197,9 +221,12 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { unsigned int rate = params_rate(hw_params); + unsigned int frames_per_period = params_period_size(hw_params); + unsigned int frames_per_buffer = params_buffer_size(hw_params); mutex_lock(&bebob->mutex); - err = snd_bebob_stream_reserve_duplex(bebob, rate); + err = snd_bebob_stream_reserve_duplex(bebob, rate, + frames_per_period, frames_per_buffer); if (err >= 0) ++bebob->substreams_counter; mutex_unlock(&bebob->mutex); @@ -286,31 +313,33 @@ pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd) return 0; } -static snd_pcm_uframes_t -pcm_capture_pointer(struct snd_pcm_substream *sbstrm) +static snd_pcm_uframes_t pcm_capture_pointer(struct snd_pcm_substream *sbstrm) { struct snd_bebob *bebob = sbstrm->private_data; - return amdtp_stream_pcm_pointer(&bebob->tx_stream); + + return amdtp_domain_stream_pcm_pointer(&bebob->domain, + &bebob->tx_stream); } -static snd_pcm_uframes_t -pcm_playback_pointer(struct snd_pcm_substream *sbstrm) +static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm) { struct snd_bebob *bebob = sbstrm->private_data; - return amdtp_stream_pcm_pointer(&bebob->rx_stream); + + return amdtp_domain_stream_pcm_pointer(&bebob->domain, + &bebob->rx_stream); } static int pcm_capture_ack(struct snd_pcm_substream *substream) { struct snd_bebob *bebob = substream->private_data; - return amdtp_stream_pcm_ack(&bebob->tx_stream); + return amdtp_domain_stream_pcm_ack(&bebob->domain, &bebob->tx_stream); } static int pcm_playback_ack(struct snd_pcm_substream *substream) { struct snd_bebob *bebob = substream->private_data; - return amdtp_stream_pcm_ack(&bebob->rx_stream); + return amdtp_domain_stream_pcm_ack(&bebob->domain, &bebob->rx_stream); } int snd_bebob_create_pcm_devices(struct snd_bebob *bebob) diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index 6c1497d9f52b..f7f0db5aa811 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c @@ -553,7 +553,9 @@ static int keep_resources(struct snd_bebob *bebob, struct amdtp_stream *stream, return cmp_connection_reserve(conn, amdtp_stream_get_max_payload(stream)); } -int snd_bebob_stream_reserve_duplex(struct snd_bebob *bebob, unsigned int rate) +int snd_bebob_stream_reserve_duplex(struct snd_bebob *bebob, unsigned int rate, + unsigned int frames_per_period, + unsigned int frames_per_buffer) { unsigned int curr_rate; int err; @@ -606,6 +608,14 @@ int snd_bebob_stream_reserve_duplex(struct snd_bebob *bebob, unsigned int rate) cmp_connection_release(&bebob->out_conn); return err; } + + err = amdtp_domain_set_events_per_period(&bebob->domain, + frames_per_period, frames_per_buffer); + if (err < 0) { + cmp_connection_release(&bebob->out_conn); + cmp_connection_release(&bebob->in_conn); + return err; + } } return 0; @@ -647,7 +657,15 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob) if (err < 0) goto error; - err = amdtp_domain_start(&bebob->domain); + // The device postpones start of transmission mostly for 1 sec + // after receives packets firstly. For safe, IR context starts + // 1.5 sec (=12000 cycles) later. This is within 2.0 sec + // (=CALLBACK_TIMEOUT). + // Furthermore, some devices transfer isoc packets with + // discontinuous counter in the beginning of packet streaming. + // The delay has an effect to avoid detection of this + // discontinuity. + err = amdtp_domain_start(&bebob->domain, 12000); if (err < 0) goto error; |