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

Commit 7a0f55ae authored by Andrej Krutak's avatar Andrej Krutak Committed by Takashi Iwai
Browse files

ALSA: line6: Support assymetrical in/out configurations



Splits max_packet_size to max_packet_size_in/out (e.g. for
different channel counts).

Signed-off-by: default avatarAndrej Krutak <dev@andree.sk>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 79faa2b0
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -44,13 +44,13 @@ static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm)
		struct usb_iso_packet_descriptor *fin =
		    &urb_in->iso_frame_desc[i];
		fin->offset = urb_size;
		fin->length = line6pcm->max_packet_size;
		urb_size += line6pcm->max_packet_size;
		fin->length = line6pcm->max_packet_size_in;
		urb_size += line6pcm->max_packet_size_in;
	}

	urb_in->transfer_buffer =
	    line6pcm->in.buffer +
	    index * LINE6_ISO_PACKETS * line6pcm->max_packet_size;
	    index * LINE6_ISO_PACKETS * line6pcm->max_packet_size_in;
	urb_in->transfer_buffer_length = urb_size;
	urb_in->context = line6pcm;

@@ -173,10 +173,10 @@ static void audio_in_callback(struct urb *urb)
		fbuf = urb->transfer_buffer + fin->offset;
		fsize = fin->actual_length;

		if (fsize > line6pcm->max_packet_size) {
		if (fsize > line6pcm->max_packet_size_in) {
			dev_err(line6pcm->line6->ifcdev,
				"driver and/or device bug: packet too large (%d > %d)\n",
				fsize, line6pcm->max_packet_size);
				fsize, line6pcm->max_packet_size_in);
		}

		length += fsize;
+19 −14
Original line number Diff line number Diff line
@@ -146,16 +146,20 @@ get_stream(struct snd_line6_pcm *line6pcm, int direction)
}

/* allocate a buffer if not opened yet;
 * call this in line6pcm.state_change mutex
 * call this in line6pcm.state_mutex
 */
static int line6_buffer_acquire(struct snd_line6_pcm *line6pcm,
				struct line6_pcm_stream *pstr, int type)
				struct line6_pcm_stream *pstr, int direction, int type)
{
	const int pkt_size =
		(direction == SNDRV_PCM_STREAM_PLAYBACK) ?
			line6pcm->max_packet_size_out :
			line6pcm->max_packet_size_in;

	/* Invoked multiple times in a row so allocate once only */
	if (!test_and_set_bit(type, &pstr->opened) && !pstr->buffer) {
		pstr->buffer = kmalloc(line6pcm->line6->iso_buffers *
				       LINE6_ISO_PACKETS *
				       line6pcm->max_packet_size, GFP_KERNEL);
				       LINE6_ISO_PACKETS * pkt_size, GFP_KERNEL);
		if (!pstr->buffer)
			return -ENOMEM;
	}
@@ -163,12 +167,11 @@ static int line6_buffer_acquire(struct snd_line6_pcm *line6pcm,
}

/* free a buffer if all streams are closed;
 * call this in line6pcm.state_change mutex
 * call this in line6pcm.state_mutex
 */
static void line6_buffer_release(struct snd_line6_pcm *line6pcm,
				 struct line6_pcm_stream *pstr, int type)
{

	clear_bit(type, &pstr->opened);
	if (!pstr->opened) {
		line6_wait_clear_audio_urbs(line6pcm, pstr);
@@ -195,6 +198,7 @@ static int line6_stream_start(struct snd_line6_pcm *line6pcm, int direction,
		else
			ret = line6_submit_audio_in_all_urbs(line6pcm);
	}

	if (ret < 0)
		clear_bit(type, &pstr->running);
	spin_unlock_irqrestore(&pstr->lock, flags);
@@ -290,7 +294,7 @@ int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type)
	mutex_lock(&line6pcm->state_mutex);
	for (dir = 0; dir < 2; dir++) {
		pstr = get_stream(line6pcm, dir);
		ret = line6_buffer_acquire(line6pcm, pstr, type);
		ret = line6_buffer_acquire(line6pcm, pstr, dir, type);
		if (ret < 0)
			goto error;
		if (!pstr->running)
@@ -335,7 +339,8 @@ int snd_line6_hw_params(struct snd_pcm_substream *substream,
	struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);

	mutex_lock(&line6pcm->state_mutex);
	ret = line6_buffer_acquire(line6pcm, pstr, LINE6_STREAM_PCM);
	ret = line6_buffer_acquire(line6pcm, pstr, substream->stream,
	                           LINE6_STREAM_PCM);
	if (ret < 0)
		goto error;

@@ -530,12 +535,12 @@ int line6_init_pcm(struct usb_line6 *line6,
	line6pcm->volume_monitor = 255;
	line6pcm->line6 = line6;

	/* Read and write buffers are sized identically, so choose minimum */
	line6pcm->max_packet_size = min(
	line6pcm->max_packet_size_in =
		usb_maxpacket(line6->usbdev,
				usb_rcvisocpipe(line6->usbdev, ep_read), 0),
			usb_rcvisocpipe(line6->usbdev, ep_read), 0);
	line6pcm->max_packet_size_out =
		usb_maxpacket(line6->usbdev,
				usb_sndisocpipe(line6->usbdev, ep_write), 1));
			usb_sndisocpipe(line6->usbdev, ep_write), 1);

	spin_lock_init(&line6pcm->out.lock);
	spin_lock_init(&line6pcm->in.lock);
+3 −2
Original line number Diff line number Diff line
@@ -156,11 +156,12 @@ struct snd_line6_pcm {
	/* Previously captured frame (for software monitoring) */
	unsigned char *prev_fbuf;

	/* Size of previously captured frame (for software monitoring) */
	/* Size of previously captured frame (for software monitoring/sync) */
	int prev_fsize;

	/* Maximum size of USB packet */
	int max_packet_size;
	int max_packet_size_in;
	int max_packet_size_out;

	/* PCM playback volume (left and right) */
	int volume_playback[2];
+1 −1
Original line number Diff line number Diff line
@@ -195,7 +195,7 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
	urb_frames = urb_size / bytes_per_frame;
	urb_out->transfer_buffer =
	    line6pcm->out.buffer +
	    index * LINE6_ISO_PACKETS * line6pcm->max_packet_size;
	    index * LINE6_ISO_PACKETS * line6pcm->max_packet_size_out;
	urb_out->transfer_buffer_length = urb_size;
	urb_out->context = line6pcm;