提交 8d1c2694 编写于 作者: T Takashi Sakamoto 提交者: Takashi Iwai

ALSA: bebob: keep duplex streams always to keep internal multiplexer 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: NKim Tore Jensen <kim@incendio.no>
Signed-off-by: NTakashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: NTakashi Iwai <tiwai@suse.de>
上级 c4d860a0
...@@ -97,8 +97,7 @@ struct snd_bebob { ...@@ -97,8 +97,7 @@ struct snd_bebob {
struct amdtp_stream rx_stream; struct amdtp_stream rx_stream;
struct cmp_connection out_conn; struct cmp_connection out_conn;
struct cmp_connection in_conn; struct cmp_connection in_conn;
atomic_t capture_substreams; atomic_t substreams_counter;
atomic_t playback_substreams;
struct snd_bebob_stream_formation struct snd_bebob_stream_formation
tx_stream_formations[SND_BEBOB_STRM_FMT_ENTRIES]; tx_stream_formations[SND_BEBOB_STRM_FMT_ENTRIES];
......
...@@ -17,7 +17,7 @@ static int midi_capture_open(struct snd_rawmidi_substream *substream) ...@@ -17,7 +17,7 @@ static int midi_capture_open(struct snd_rawmidi_substream *substream)
if (err < 0) if (err < 0)
goto end; goto end;
atomic_inc(&bebob->capture_substreams); atomic_inc(&bebob->substreams_counter);
err = snd_bebob_stream_start_duplex(bebob, 0); err = snd_bebob_stream_start_duplex(bebob, 0);
if (err < 0) if (err < 0)
snd_bebob_stream_lock_release(bebob); snd_bebob_stream_lock_release(bebob);
...@@ -34,7 +34,7 @@ static int midi_playback_open(struct snd_rawmidi_substream *substream) ...@@ -34,7 +34,7 @@ static int midi_playback_open(struct snd_rawmidi_substream *substream)
if (err < 0) if (err < 0)
goto end; goto end;
atomic_inc(&bebob->playback_substreams); atomic_inc(&bebob->substreams_counter);
err = snd_bebob_stream_start_duplex(bebob, 0); err = snd_bebob_stream_start_duplex(bebob, 0);
if (err < 0) if (err < 0)
snd_bebob_stream_lock_release(bebob); snd_bebob_stream_lock_release(bebob);
...@@ -46,7 +46,7 @@ static int midi_capture_close(struct snd_rawmidi_substream *substream) ...@@ -46,7 +46,7 @@ static int midi_capture_close(struct snd_rawmidi_substream *substream)
{ {
struct snd_bebob *bebob = substream->rmidi->private_data; 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_stop_duplex(bebob);
snd_bebob_stream_lock_release(bebob); snd_bebob_stream_lock_release(bebob);
...@@ -57,7 +57,7 @@ static int midi_playback_close(struct snd_rawmidi_substream *substream) ...@@ -57,7 +57,7 @@ static int midi_playback_close(struct snd_rawmidi_substream *substream)
{ {
struct snd_bebob *bebob = substream->rmidi->private_data; 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_stop_duplex(bebob);
snd_bebob_stream_lock_release(bebob); snd_bebob_stream_lock_release(bebob);
......
...@@ -213,7 +213,7 @@ pcm_capture_hw_params(struct snd_pcm_substream *substream, ...@@ -213,7 +213,7 @@ pcm_capture_hw_params(struct snd_pcm_substream *substream,
struct snd_bebob *bebob = substream->private_data; struct snd_bebob *bebob = substream->private_data;
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) 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, amdtp_stream_set_pcm_format(&bebob->tx_stream,
params_format(hw_params)); params_format(hw_params));
return snd_pcm_lib_alloc_vmalloc_buffer(substream, return snd_pcm_lib_alloc_vmalloc_buffer(substream,
...@@ -226,7 +226,7 @@ pcm_playback_hw_params(struct snd_pcm_substream *substream, ...@@ -226,7 +226,7 @@ pcm_playback_hw_params(struct snd_pcm_substream *substream,
struct snd_bebob *bebob = substream->private_data; struct snd_bebob *bebob = substream->private_data;
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) 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, amdtp_stream_set_pcm_format(&bebob->rx_stream,
params_format(hw_params)); params_format(hw_params));
return snd_pcm_lib_alloc_vmalloc_buffer(substream, return snd_pcm_lib_alloc_vmalloc_buffer(substream,
...@@ -239,7 +239,7 @@ pcm_capture_hw_free(struct snd_pcm_substream *substream) ...@@ -239,7 +239,7 @@ pcm_capture_hw_free(struct snd_pcm_substream *substream)
struct snd_bebob *bebob = substream->private_data; struct snd_bebob *bebob = substream->private_data;
if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) 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); snd_bebob_stream_stop_duplex(bebob);
...@@ -251,7 +251,7 @@ pcm_playback_hw_free(struct snd_pcm_substream *substream) ...@@ -251,7 +251,7 @@ pcm_playback_hw_free(struct snd_pcm_substream *substream)
struct snd_bebob *bebob = substream->private_data; struct snd_bebob *bebob = substream->private_data;
if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) 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); snd_bebob_stream_stop_duplex(bebob);
......
...@@ -574,7 +574,6 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate) ...@@ -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 snd_bebob_rate_spec *rate_spec = bebob->spec->rate;
struct amdtp_stream *master, *slave; struct amdtp_stream *master, *slave;
atomic_t *slave_substreams;
enum cip_flags sync_mode; enum cip_flags sync_mode;
unsigned int curr_rate; unsigned int curr_rate;
bool updated = false; bool updated = false;
...@@ -599,8 +598,7 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate) ...@@ -599,8 +598,7 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate)
mutex_lock(&bebob->mutex); mutex_lock(&bebob->mutex);
/* Need no substreams */ /* Need no substreams */
if (atomic_read(&bebob->playback_substreams) == 0 && if (atomic_read(&bebob->substreams_counter) == 0)
atomic_read(&bebob->capture_substreams) == 0)
goto end; goto end;
err = get_sync_mode(bebob, &sync_mode); err = get_sync_mode(bebob, &sync_mode);
...@@ -609,11 +607,9 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate) ...@@ -609,11 +607,9 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate)
if (sync_mode == CIP_SYNC_TO_DEVICE) { if (sync_mode == CIP_SYNC_TO_DEVICE) {
master = &bebob->tx_stream; master = &bebob->tx_stream;
slave = &bebob->rx_stream; slave = &bebob->rx_stream;
slave_substreams = &bebob->playback_substreams;
} else { } else {
master = &bebob->rx_stream; master = &bebob->rx_stream;
slave = &bebob->tx_stream; slave = &bebob->tx_stream;
slave_substreams = &bebob->capture_substreams;
} }
/* /*
...@@ -714,7 +710,7 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate) ...@@ -714,7 +710,7 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate)
} }
/* start slave if needed */ /* 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); err = start_stream(bebob, slave, rate);
if (err < 0) { if (err < 0) {
dev_err(&bebob->unit->device, dev_err(&bebob->unit->device,
...@@ -740,31 +736,25 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate) ...@@ -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) void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob)
{ {
struct amdtp_stream *master, *slave; struct amdtp_stream *master, *slave;
atomic_t *master_substreams, *slave_substreams;
if (bebob->master == &bebob->rx_stream) { if (bebob->master == &bebob->rx_stream) {
slave = &bebob->tx_stream; slave = &bebob->tx_stream;
master = &bebob->rx_stream; master = &bebob->rx_stream;
slave_substreams = &bebob->capture_substreams;
master_substreams = &bebob->playback_substreams;
} else { } else {
slave = &bebob->rx_stream; slave = &bebob->rx_stream;
master = &bebob->tx_stream; master = &bebob->tx_stream;
slave_substreams = &bebob->playback_substreams;
master_substreams = &bebob->capture_substreams;
} }
mutex_lock(&bebob->mutex); 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_pcm_abort(slave);
amdtp_stream_stop(slave); amdtp_stream_stop(slave);
if (atomic_read(master_substreams) == 0) { break_both_connections(bebob);
amdtp_stream_pcm_abort(master);
amdtp_stream_stop(master);
break_both_connections(bebob);
}
} }
mutex_unlock(&bebob->mutex); mutex_unlock(&bebob->mutex);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册