Skip to content

Commit

Permalink
ALSA: bebob: keep duplex streams always to keep internal multiplexer …
Browse files Browse the repository at this point in the history
…properly

Behringer FCA610 transmits packets with periodic noisy PCM samples
when receiving no streams, and generates a bit noisy sound.

ALSA BeBoB driver is programmed to establish both in/out connections
when starting streaming, then transfers packets as userspace applications
requested. This means that there's a case that one of incoming/outgoing
streams is running, to save CPU and bandwidth usage. Although, it's natural
to start transferring packets in both direction.

This commit makes this driver to keeps duplex streams always.

Tested-by: Kim Tore Jensen <[email protected]>
Signed-off-by: Takashi Sakamoto <[email protected]>
Signed-off-by: Takashi Iwai <[email protected]>
  • Loading branch information
takaswie authored and tiwai committed Jun 15, 2015
1 parent c4d860a commit 8d1c269
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 27 deletions.
3 changes: 1 addition & 2 deletions sound/firewire/bebob/bebob.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,7 @@ struct snd_bebob {
struct amdtp_stream rx_stream;
struct cmp_connection out_conn;
struct cmp_connection in_conn;
atomic_t capture_substreams;
atomic_t playback_substreams;
atomic_t substreams_counter;

struct snd_bebob_stream_formation
tx_stream_formations[SND_BEBOB_STRM_FMT_ENTRIES];
Expand Down
8 changes: 4 additions & 4 deletions sound/firewire/bebob/bebob_midi.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ static int midi_capture_open(struct snd_rawmidi_substream *substream)
if (err < 0)
goto end;

atomic_inc(&bebob->capture_substreams);
atomic_inc(&bebob->substreams_counter);
err = snd_bebob_stream_start_duplex(bebob, 0);
if (err < 0)
snd_bebob_stream_lock_release(bebob);
Expand All @@ -34,7 +34,7 @@ static int midi_playback_open(struct snd_rawmidi_substream *substream)
if (err < 0)
goto end;

atomic_inc(&bebob->playback_substreams);
atomic_inc(&bebob->substreams_counter);
err = snd_bebob_stream_start_duplex(bebob, 0);
if (err < 0)
snd_bebob_stream_lock_release(bebob);
Expand All @@ -46,7 +46,7 @@ static int midi_capture_close(struct snd_rawmidi_substream *substream)
{
struct snd_bebob *bebob = substream->rmidi->private_data;

atomic_dec(&bebob->capture_substreams);
atomic_dec(&bebob->substreams_counter);
snd_bebob_stream_stop_duplex(bebob);

snd_bebob_stream_lock_release(bebob);
Expand All @@ -57,7 +57,7 @@ static int midi_playback_close(struct snd_rawmidi_substream *substream)
{
struct snd_bebob *bebob = substream->rmidi->private_data;

atomic_dec(&bebob->playback_substreams);
atomic_dec(&bebob->substreams_counter);
snd_bebob_stream_stop_duplex(bebob);

snd_bebob_stream_lock_release(bebob);
Expand Down
8 changes: 4 additions & 4 deletions sound/firewire/bebob/bebob_pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ pcm_capture_hw_params(struct snd_pcm_substream *substream,
struct snd_bebob *bebob = substream->private_data;

if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN)
atomic_inc(&bebob->capture_substreams);
atomic_inc(&bebob->substreams_counter);
amdtp_stream_set_pcm_format(&bebob->tx_stream,
params_format(hw_params));
return snd_pcm_lib_alloc_vmalloc_buffer(substream,
Expand All @@ -226,7 +226,7 @@ pcm_playback_hw_params(struct snd_pcm_substream *substream,
struct snd_bebob *bebob = substream->private_data;

if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN)
atomic_inc(&bebob->playback_substreams);
atomic_inc(&bebob->substreams_counter);
amdtp_stream_set_pcm_format(&bebob->rx_stream,
params_format(hw_params));
return snd_pcm_lib_alloc_vmalloc_buffer(substream,
Expand All @@ -239,7 +239,7 @@ pcm_capture_hw_free(struct snd_pcm_substream *substream)
struct snd_bebob *bebob = substream->private_data;

if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
atomic_dec(&bebob->capture_substreams);
atomic_dec(&bebob->substreams_counter);

snd_bebob_stream_stop_duplex(bebob);

Expand All @@ -251,7 +251,7 @@ pcm_playback_hw_free(struct snd_pcm_substream *substream)
struct snd_bebob *bebob = substream->private_data;

if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
atomic_dec(&bebob->playback_substreams);
atomic_dec(&bebob->substreams_counter);

snd_bebob_stream_stop_duplex(bebob);

Expand Down
24 changes: 7 additions & 17 deletions sound/firewire/bebob/bebob_stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,6 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate)
{
struct snd_bebob_rate_spec *rate_spec = bebob->spec->rate;
struct amdtp_stream *master, *slave;
atomic_t *slave_substreams;
enum cip_flags sync_mode;
unsigned int curr_rate;
bool updated = false;
Expand All @@ -599,8 +598,7 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate)
mutex_lock(&bebob->mutex);

/* Need no substreams */
if (atomic_read(&bebob->playback_substreams) == 0 &&
atomic_read(&bebob->capture_substreams) == 0)
if (atomic_read(&bebob->substreams_counter) == 0)
goto end;

err = get_sync_mode(bebob, &sync_mode);
Expand All @@ -609,11 +607,9 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate)
if (sync_mode == CIP_SYNC_TO_DEVICE) {
master = &bebob->tx_stream;
slave = &bebob->rx_stream;
slave_substreams = &bebob->playback_substreams;
} else {
master = &bebob->rx_stream;
slave = &bebob->tx_stream;
slave_substreams = &bebob->capture_substreams;
}

/*
Expand Down Expand Up @@ -714,7 +710,7 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate)
}

/* start slave if needed */
if (atomic_read(slave_substreams) > 0 && !amdtp_stream_running(slave)) {
if (!amdtp_stream_running(slave)) {
err = start_stream(bebob, slave, rate);
if (err < 0) {
dev_err(&bebob->unit->device,
Expand All @@ -740,31 +736,25 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate)
void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob)
{
struct amdtp_stream *master, *slave;
atomic_t *master_substreams, *slave_substreams;

if (bebob->master == &bebob->rx_stream) {
slave = &bebob->tx_stream;
master = &bebob->rx_stream;
slave_substreams = &bebob->capture_substreams;
master_substreams = &bebob->playback_substreams;
} else {
slave = &bebob->rx_stream;
master = &bebob->tx_stream;
slave_substreams = &bebob->playback_substreams;
master_substreams = &bebob->capture_substreams;
}

mutex_lock(&bebob->mutex);

if (atomic_read(slave_substreams) == 0) {
if (atomic_read(&bebob->substreams_counter) == 0) {
amdtp_stream_pcm_abort(master);
amdtp_stream_stop(master);

amdtp_stream_pcm_abort(slave);
amdtp_stream_stop(slave);

if (atomic_read(master_substreams) == 0) {
amdtp_stream_pcm_abort(master);
amdtp_stream_stop(master);
break_both_connections(bebob);
}
break_both_connections(bebob);
}

mutex_unlock(&bebob->mutex);
Expand Down

0 comments on commit 8d1c269

Please sign in to comment.