Compare commits

..

No commits in common. "main" and "us200-boot-delay-fix" have entirely different histories.

4 changed files with 27 additions and 86 deletions

View File

@ -46,12 +46,10 @@ void tascam_free_urbs(struct tascam_card *tascam)
}
}
if (tascam->midi_out_urb) {
if (tascam->midi_out_buf)
usb_free_coherent(tascam->dev, MIDI_PACKET_SIZE, tascam->midi_out_buf, tascam->midi_out_urb->transfer_dma);
usb_free_urb(tascam->midi_out_urb);
}
if (tascam->midi_in_urb) {
if (tascam->midi_in_buf)
usb_free_coherent(tascam->dev, MIDI_PACKET_SIZE, tascam->midi_in_buf, tascam->midi_in_urb->transfer_dma);
usb_free_urb(tascam->midi_in_urb);
}
@ -71,12 +69,12 @@ int tascam_alloc_urbs(struct tascam_card *tascam)
for (i = 0; i < NUM_PLAYBACK_URBS; i++) {
struct urb *urb = usb_alloc_urb(PLAYBACK_URB_PACKETS, GFP_KERNEL);
if (!urb)
goto error_free_urbs;
return -ENOMEM;
tascam->playback_urbs[i] = urb;
urb->transfer_buffer = usb_alloc_coherent(tascam->dev, tascam->playback_urb_alloc_size,
GFP_KERNEL, &urb->transfer_dma);
if (!urb->transfer_buffer)
goto error_free_urbs;
return -ENOMEM;
urb->dev = tascam->dev;
urb->pipe = usb_sndisocpipe(tascam->dev, EP_AUDIO_OUT);
urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
@ -89,12 +87,12 @@ int tascam_alloc_urbs(struct tascam_card *tascam)
for (i = 0; i < NUM_FEEDBACK_URBS; i++) {
struct urb *urb = usb_alloc_urb(FEEDBACK_URB_PACKETS, GFP_KERNEL);
if (!urb)
goto error_free_urbs;
return -ENOMEM;
tascam->feedback_urbs[i] = urb;
urb->transfer_buffer = usb_alloc_coherent(tascam->dev, tascam->feedback_urb_alloc_size,
GFP_KERNEL, &urb->transfer_dma);
if (!urb->transfer_buffer)
goto error_free_urbs;
return -ENOMEM;
urb->dev = tascam->dev;
urb->pipe = usb_rcvisocpipe(tascam->dev, EP_PLAYBACK_FEEDBACK);
urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
@ -107,20 +105,16 @@ int tascam_alloc_urbs(struct tascam_card *tascam)
struct urb *urb = usb_alloc_urb(0, GFP_KERNEL);
void *buf;
if (!urb)
goto error_free_urbs;
return -ENOMEM;
tascam->capture_urbs[i] = urb;
buf = usb_alloc_coherent(tascam->dev, CAPTURE_PACKET_SIZE, GFP_KERNEL, &urb->transfer_dma);
if (!buf)
goto error_free_urbs;
return -ENOMEM;
usb_fill_bulk_urb(urb, tascam->dev, usb_rcvbulkpipe(tascam->dev, EP_AUDIO_IN),
buf, CAPTURE_PACKET_SIZE, capture_urb_complete, tascam);
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
}
return 0;
error_free_urbs:
tascam_free_urbs(tascam);
return -ENOMEM;
}
/**
@ -167,10 +161,8 @@ static int tascam_resume(struct usb_interface *intf)
if (!tascam)
return 0;
if (usb_set_interface(tascam->dev, 0, 1) < 0)
dev_warn(&tascam->dev->dev, "Failed to set interface 0 on resume\n");
if (usb_set_interface(tascam->dev, 1, 1) < 0)
dev_warn(&tascam->dev->dev, "Failed to set interface 1 on resume\n");
usb_set_interface(tascam->dev, 0, 1);
usb_set_interface(tascam->dev, 1, 1);
if (tascam->current_rate > 0) {
u16 stream_mode = (tascam->dev_id == USB_PID_TASCAM_US200) ? MODE_VAL_STREAM_START_US200 : MODE_VAL_STREAM_START;
us144mkii_configure_device_for_rate(tascam, tascam->current_rate, stream_mode);
@ -263,9 +255,8 @@ static int tascam_probe(struct usb_interface *intf, const struct usb_device_id *
msleep(100);
int handshake_result = -EIO;
for (int retry = 0; retry < 3; retry++) {
handshake_result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), VENDOR_REQ_MODE_CONTROL,
int handshake_result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), VENDOR_REQ_MODE_CONTROL,
RT_D2H_VENDOR_DEV, MODE_VAL_HANDSHAKE_READ, 0x0000,
tascam->scratch_buf, 1, USB_CTRL_TIMEOUT_MS);
if (handshake_result >= 0)
@ -275,22 +266,8 @@ static int tascam_probe(struct usb_interface *intf, const struct usb_device_id *
msleep(50);
}
if (handshake_result < 0) {
dev_err(&dev->dev, "Handshake failed after all retries\n");
err = -EIO;
goto free_card;
}
err = usb_set_interface(dev, 0, 1);
if (err < 0) {
dev_err(&dev->dev, "Failed to set interface 0\n");
goto free_card;
}
err = usb_set_interface(dev, 1, 1);
if (err < 0) {
dev_err(&dev->dev, "Failed to set interface 1\n");
goto free_card;
}
usb_set_interface(dev, 0, 1);
usb_set_interface(dev, 1, 1);
u16 stream_mode = (tascam->dev_id == USB_PID_TASCAM_US200) ? MODE_VAL_STREAM_START_US200 : MODE_VAL_STREAM_START;
@ -307,8 +284,6 @@ static int tascam_probe(struct usb_interface *intf, const struct usb_device_id *
return 0;
free_card:
cancel_work_sync(&tascam->stop_work);
cancel_work_sync(&tascam->stop_pcm_work);
snd_card_free(card);
atomic_dec(&dev_idx);
return err;

View File

@ -113,6 +113,8 @@ static int tascam_midi_open(struct snd_rawmidi_substream *substream)
struct tascam_card *tascam = substream->rmidi->private_data;
int err = 0;
us144mkii_maybe_start_stream(tascam);
if (substream->stream == SNDRV_RAWMIDI_STREAM_OUTPUT) {
unsigned long flags;
spin_lock_irqsave(&tascam->midi_lock, flags);
@ -122,11 +124,13 @@ static int tascam_midi_open(struct snd_rawmidi_substream *substream)
usb_anchor_urb(tascam->midi_in_urb, &tascam->midi_anchor);
if (usb_submit_urb(tascam->midi_in_urb, GFP_KERNEL) < 0) {
usb_unanchor_urb(tascam->midi_in_urb);
return -EIO;
err = -EIO;
}
}
us144mkii_maybe_start_stream(tascam);
if (err < 0)
us144mkii_maybe_stop_stream(tascam);
return err;
}
@ -190,36 +194,16 @@ int tascam_create_midi(struct tascam_card *tascam)
tascam->rmidi = rmidi;
tascam->midi_out_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!tascam->midi_out_urb)
return -ENOMEM;
tascam->midi_in_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!tascam->midi_in_urb) {
usb_free_urb(tascam->midi_out_urb);
if (!tascam->midi_out_urb || !tascam->midi_in_urb)
return -ENOMEM;
}
tascam->midi_out_buf = usb_alloc_coherent(tascam->dev, MIDI_PACKET_SIZE,
GFP_KERNEL, &tascam->midi_out_urb->transfer_dma);
if (!tascam->midi_out_buf) {
usb_free_urb(tascam->midi_in_urb);
usb_free_urb(tascam->midi_out_urb);
tascam->midi_out_urb = NULL;
tascam->midi_in_urb = NULL;
return -ENOMEM;
}
tascam->midi_in_buf = usb_alloc_coherent(tascam->dev, MIDI_PACKET_SIZE,
GFP_KERNEL, &tascam->midi_in_urb->transfer_dma);
if (!tascam->midi_in_buf) {
usb_free_coherent(tascam->dev, MIDI_PACKET_SIZE, tascam->midi_out_buf, tascam->midi_out_urb->transfer_dma);
usb_free_urb(tascam->midi_in_urb);
usb_free_urb(tascam->midi_out_urb);
tascam->midi_out_urb = NULL;
tascam->midi_in_urb = NULL;
tascam->midi_out_buf = NULL;
if (!tascam->midi_out_buf || !tascam->midi_in_buf)
return -ENOMEM;
}
usb_fill_bulk_urb(tascam->midi_out_urb, tascam->dev,
usb_sndbulkpipe(tascam->dev, EP_MIDI_OUT),

View File

@ -87,8 +87,6 @@ int us144mkii_configure_device_for_rate(struct tascam_card *tascam, int rate, u1
goto out;
}
/* Last control message: store result in err and fall through to 'out' label.
* Earlier failures use goto out which also frees payload before returning. */
err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), VENDOR_REQ_MODE_CONTROL,
RT_H2D_VENDOR_DEV, stream_mode, 0x0000, NULL, 0, USB_CTRL_TIMEOUT_MS);
@ -157,6 +155,4 @@ void tascam_stop_pcm_work_handler(struct work_struct *work)
if (tascam->dev && tascam->playback_substream)
snd_pcm_stop(tascam->playback_substream, SNDRV_PCM_STATE_XRUN);
if (tascam->dev && tascam->capture_substream)
snd_pcm_stop(tascam->capture_substream, SNDRV_PCM_STATE_XRUN);
}

View File

@ -73,6 +73,8 @@ void us144mkii_maybe_start_stream(struct tascam_card *tascam)
{
unsigned long flags;
atomic_inc(&tascam->stream_refs);
spin_lock_irqsave(&tascam->lock, flags);
if (!atomic_read(&tascam->playback_active) && !tascam->running_ghost_playback) {
tascam->running_ghost_playback = true;
@ -83,13 +85,8 @@ void us144mkii_maybe_start_stream(struct tascam_card *tascam)
prepare_urb_descriptors(tascam);
if (submit_urbs(tascam, tascam->feedback_urbs, NUM_FEEDBACK_URBS, &tascam->feedback_anchor) < 0 ||
submit_urbs(tascam, tascam->playback_urbs, NUM_PLAYBACK_URBS, &tascam->playback_anchor) < 0) {
tascam->running_ghost_playback = false;
spin_unlock_irqrestore(&tascam->lock, flags);
return;
}
atomic_inc(&tascam->stream_refs);
submit_urbs(tascam, tascam->feedback_urbs, NUM_FEEDBACK_URBS, &tascam->feedback_anchor);
submit_urbs(tascam, tascam->playback_urbs, NUM_PLAYBACK_URBS, &tascam->playback_anchor);
}
spin_unlock_irqrestore(&tascam->lock, flags);
}
@ -171,13 +168,9 @@ static int tascam_playback_trigger(struct snd_pcm_substream *substream, int cmd)
case SNDRV_PCM_TRIGGER_RESUME:
if (!atomic_read(&tascam->playback_active)) {
atomic_set(&tascam->playback_active, 1);
/* Ghost-to-real takeover: ghost URBs are already submitted and running.
* We just flip the flag so playback_urb_complete will copy real audio data
* instead of silence. No need to submit new URBs since they're already in flight. */
/* If ghost playback is running, just takeover flag */
if (tascam->running_ghost_playback) {
tascam->running_ghost_playback = false;
/* Re-prepare descriptors with current rate in case hw_params changed */
prepare_urb_descriptors(tascam);
} else {
submit_urbs(tascam, tascam->feedback_urbs, NUM_FEEDBACK_URBS, &tascam->feedback_anchor);
submit_urbs(tascam, tascam->playback_urbs, NUM_PLAYBACK_URBS, &tascam->playback_anchor);
@ -257,13 +250,6 @@ void playback_urb_complete(struct urb *urb)
}
urb->transfer_buffer_length = total_bytes;
if (!urb->transfer_buffer) {
spin_unlock_irqrestore(&tascam->lock, flags);
usb_unanchor_urb(urb);
atomic_dec(&tascam->active_urbs);
return;
}
/* Ghost Playback: Send Silence */
if (!atomic_read(&tascam->playback_active)) {
if (tascam->running_ghost_playback) {
@ -346,7 +332,7 @@ void feedback_urb_complete(struct urb *urb)
tascam->feedback_urb_skip_count--;
} else {
for (p = 0; p < urb->number_of_packets; p++) {
if (urb->iso_frame_desc[p].actual_length > 0 && urb->transfer_buffer) {
if (urb->iso_frame_desc[p].actual_length > 0) {
u8 *d = urb->transfer_buffer + urb->iso_frame_desc[p].offset;
u32 val = (urb->iso_frame_desc[p].actual_length >= 3) ? (d[0] + d[1] + d[2]) : (d[0] * 3);
u32 target = (val << 16) / 24;