Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4b284928 authored by Clemens Ladisch's avatar Clemens Ladisch Committed by Jaroslav Kysela
Browse files

[ALSA] usb-audio: don't use empty packets at start of playback



Modules: USB generic driver

Some widespread USB interface chips with adaptive iso endpoints hang
after receiving a series of empty packets when they expect data (ALSA
bug#1585).  To avoid this, we have to send packets containing silence
(zero samples) instead.

Signed-off-by: default avatarClemens Ladisch <clemens@ladisch.de>
parent 54c63cfc
Loading
Loading
Loading
Loading
+21 −5
Original line number Diff line number Diff line
@@ -478,22 +478,38 @@ static int retire_playback_sync_urb_hs(struct snd_usb_substream *subs,
/*
 * Prepare urb for streaming before playback starts.
 *
 * We don't care about (or have) any data, so we just send a transfer delimiter.
 * We don't yet have data, so we send a frame of silence.
 */
static int prepare_startup_playback_urb(struct snd_usb_substream *subs,
					struct snd_pcm_runtime *runtime,
					struct urb *urb)
{
	unsigned int i;
	unsigned int i, offs, counts;
	struct snd_urb_ctx *ctx = urb->context;
	int stride = runtime->frame_bits >> 3;

	offs = 0;
	urb->dev = ctx->subs->dev;
	urb->number_of_packets = subs->packs_per_ms;
	for (i = 0; i < subs->packs_per_ms; ++i) {
		urb->iso_frame_desc[i].offset = 0;
		urb->iso_frame_desc[i].length = 0;
		/* calculate the size of a packet */
		if (subs->fill_max)
			counts = subs->maxframesize; /* fixed */
		else {
			subs->phase = (subs->phase & 0xffff)
				+ (subs->freqm << subs->datainterval);
			counts = subs->phase >> 16;
			if (counts > subs->maxframesize)
				counts = subs->maxframesize;
		}
	urb->transfer_buffer_length = 0;
		urb->iso_frame_desc[i].offset = offs * stride;
		urb->iso_frame_desc[i].length = counts * stride;
		offs += counts;
	}
	urb->transfer_buffer_length = offs * stride;
	memset(urb->transfer_buffer,
	       subs->cur_audiofmt->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0,
	       offs * stride);
	return 0;
}