From 32986d79341ae005a4d5bb6853a863025f0064f7 Mon Sep 17 00:00:00 2001 From: Marvin Date: Tue, 9 Jun 2026 15:23:03 -0300 Subject: [PATCH] Keep playback URBs running continuously between open/close cycles via ghost mode --- us144mkii_pcm.c | 1 + us144mkii_playback.c | 28 +++++++++++++++++----------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/us144mkii_pcm.c b/us144mkii_pcm.c index f531406..39e2c29 100644 --- a/us144mkii_pcm.c +++ b/us144mkii_pcm.c @@ -128,6 +128,7 @@ int tascam_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_ usb_kill_anchored_urbs(&tascam->feedback_anchor); usb_kill_anchored_urbs(&tascam->capture_anchor); atomic_set(&tascam->active_urbs, 0); + tascam->running_ghost_playback = false; u16 stream_mode = (tascam->dev_id == USB_PID_TASCAM_US200) ? MODE_VAL_STREAM_START_US200 : MODE_VAL_STREAM_START; err = us144mkii_configure_device_for_rate(tascam, rate, stream_mode); diff --git a/us144mkii_playback.c b/us144mkii_playback.c index cd2832b..0234993 100644 --- a/us144mkii_playback.c +++ b/us144mkii_playback.c @@ -130,8 +130,6 @@ static int tascam_playback_close(struct snd_pcm_substream *substream) { struct tascam_card *tascam = snd_pcm_substream_chip(substream); atomic_set(&tascam->playback_active, 0); - usb_kill_anchored_urbs(&tascam->playback_anchor); - usb_kill_anchored_urbs(&tascam->feedback_anchor); tascam->playback_substream = NULL; return 0; } @@ -140,18 +138,21 @@ static int tascam_playback_prepare(struct snd_pcm_substream *substream) { struct tascam_card *tascam = snd_pcm_substream_chip(substream); - usb_kill_anchored_urbs(&tascam->playback_anchor); - usb_kill_anchored_urbs(&tascam->feedback_anchor); - tascam->driver_playback_pos = 0; tascam->playback_frames_consumed = 0; tascam->last_pb_period_pos = 0; tascam->feedback_synced = false; - tascam->running_ghost_playback = false; + + if (tascam->running_ghost_playback) + return 0; + + usb_kill_anchored_urbs(&tascam->playback_anchor); + usb_kill_anchored_urbs(&tascam->feedback_anchor); + tascam->feedback_urb_skip_count = 4; tascam->phase_accum = 0; tascam->freq_q16 = div_u64(((u64)tascam->current_rate << 16), 8000); - + tascam->running_ghost_playback = false; prepare_urb_descriptors(tascam); return 0; } @@ -181,9 +182,7 @@ static int tascam_playback_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: atomic_set(&tascam->playback_active, 0); - /* Fall back to ghost playback if capture/midi active */ - if (atomic_read(&tascam->stream_refs) > 0) - tascam->running_ghost_playback = true; + tascam->running_ghost_playback = true; break; default: ret = -EINVAL; @@ -199,8 +198,15 @@ static snd_pcm_uframes_t tascam_playback_pointer(struct snd_pcm_substream *subst unsigned long flags; u64 pos; - if (!atomic_read(&tascam->playback_active)) + if (!atomic_read(&tascam->playback_active)) { + if (tascam->running_ghost_playback) { + spin_lock_irqsave(&tascam->lock, flags); + pos = tascam->playback_frames_consumed; + spin_unlock_irqrestore(&tascam->lock, flags); + return (snd_pcm_uframes_t)pos; + } return 0; + } spin_lock_irqsave(&tascam->lock, flags); pos = tascam->playback_frames_consumed;