Exemple #1
0
int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels)
{
	unsigned long flags_old =
	    __sync_fetch_and_or(&line6pcm->flags, channels);
	unsigned long flags_new = flags_old | channels;
	int err = 0;
	
	line6pcm->prev_fbuf = NULL;

	if (test_flags(flags_old, flags_new, MASK_CAPTURE)) {
		/*
		   Waiting for completion of active URBs in the stop handler is
		   a bug, we therefore report an error if capturing is restarted
		   too soon.
		 */
		if (line6pcm->active_urb_in | line6pcm->unlink_urb_in)
			return -EBUSY;

		if (!(flags_new & MASK_PCM_ALSA_CAPTURE)) {
			err = line6_alloc_capture_buffer(line6pcm);

			if (err < 0)
				goto pcm_start_error;
		}

		line6pcm->count_in = 0;
		line6pcm->prev_fsize = 0;
		err = line6_submit_audio_in_all_urbs(line6pcm);

		if (err < 0)
			goto pcm_start_error;
	}

	if (test_flags(flags_old, flags_new, MASK_PLAYBACK)) {
		/*
		   See comment above regarding PCM restart.
		 */
		if (line6pcm->active_urb_out | line6pcm->unlink_urb_out)
			return -EBUSY;

		if (!(flags_new & MASK_PCM_ALSA_PLAYBACK)) {
			err = line6_alloc_playback_buffer(line6pcm);

			if (err < 0)
				goto pcm_start_error;
		}

		line6pcm->count_out = 0;
		err = line6_submit_audio_out_all_urbs(line6pcm);

		if (err < 0)
			goto pcm_start_error;
	}

	return 0;

pcm_start_error:
	__sync_fetch_and_and(&line6pcm->flags, ~channels);
	return err;
}
Exemple #2
0
/* start a PCM stream */
static int line6_stream_start(struct snd_line6_pcm *line6pcm, int direction,
			      int type)
{
	unsigned long flags;
	struct line6_pcm_stream *pstr = get_stream(line6pcm, direction);
	int ret = 0;

	spin_lock_irqsave(&pstr->lock, flags);
	if (!test_and_set_bit(type, &pstr->running) &&
	    !(pstr->active_urbs || pstr->unlink_urbs)) {
		pstr->count = 0;
		/* Submit all currently available URBs */
		if (direction == SNDRV_PCM_STREAM_PLAYBACK)
			ret = line6_submit_audio_out_all_urbs(line6pcm);
		else
			ret = line6_submit_audio_in_all_urbs(line6pcm);
	}
	if (ret < 0)
		clear_bit(type, &pstr->running);
	spin_unlock_irqrestore(&pstr->lock, flags);
	return ret;
}
Exemple #3
0
int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels)
{
	unsigned long flags_old, flags_new, flags_final;
	int err;

	do {
		flags_old = ACCESS_ONCE(line6pcm->flags);
		flags_new = flags_old | channels;
	} while (cmpxchg(&line6pcm->flags, flags_old, flags_new) != flags_old);

	flags_final = flags_old;

	line6pcm->prev_fbuf = NULL;

	if (test_flags(flags_old, flags_new, LINE6_BITS_CAPTURE_BUFFER)) {
		/* Invoked multiple times in a row so allocate once only */
		if (!line6pcm->buffer_in) {
			line6pcm->buffer_in =
				kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
					line6pcm->max_packet_size, GFP_KERNEL);
			if (!line6pcm->buffer_in) {
				err = -ENOMEM;
				goto pcm_acquire_error;
			}

			flags_final |= channels & LINE6_BITS_CAPTURE_BUFFER;
		}
	}

	if (test_flags(flags_old, flags_new, LINE6_BITS_CAPTURE_STREAM)) {
		/*
		   Waiting for completion of active URBs in the stop handler is
		   a bug, we therefore report an error if capturing is restarted
		   too soon.
		 */
		if (line6pcm->active_urb_in | line6pcm->unlink_urb_in) {
			dev_err(line6pcm->line6->ifcdev, "Device not yet ready\n");
			return -EBUSY;
		}

		line6pcm->count_in = 0;
		line6pcm->prev_fsize = 0;
		err = line6_submit_audio_in_all_urbs(line6pcm);

		if (err < 0)
			goto pcm_acquire_error;

		flags_final |= channels & LINE6_BITS_CAPTURE_STREAM;
	}

	if (test_flags(flags_old, flags_new, LINE6_BITS_PLAYBACK_BUFFER)) {
		/* Invoked multiple times in a row so allocate once only */
		if (!line6pcm->buffer_out) {
			line6pcm->buffer_out =
				kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
					line6pcm->max_packet_size, GFP_KERNEL);
			if (!line6pcm->buffer_out) {
				err = -ENOMEM;
				goto pcm_acquire_error;
			}

			flags_final |= channels & LINE6_BITS_PLAYBACK_BUFFER;
		}
	}

	if (test_flags(flags_old, flags_new, LINE6_BITS_PLAYBACK_STREAM)) {
		/*
		  See comment above regarding PCM restart.
		*/
		if (line6pcm->active_urb_out | line6pcm->unlink_urb_out) {
			dev_err(line6pcm->line6->ifcdev, "Device not yet ready\n");
			return -EBUSY;
		}

		line6pcm->count_out = 0;
		err = line6_submit_audio_out_all_urbs(line6pcm);

		if (err < 0)
			goto pcm_acquire_error;

		flags_final |= channels & LINE6_BITS_PLAYBACK_STREAM;
	}

	return 0;

pcm_acquire_error:
	/*
	   If not all requested resources/streams could be obtained, release
	   those which were successfully obtained (if any).
	*/
	line6_pcm_release(line6pcm, flags_final & channels);
	return err;
}
Exemple #4
0
int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels)
{
	unsigned long flags_old =
	    __sync_fetch_and_or(&line6pcm->flags, channels);
	unsigned long flags_new = flags_old | channels;
	int err = 0;

#if LINE6_BACKUP_MONITOR_SIGNAL
	if (!(line6pcm->line6->properties->capabilities & LINE6_BIT_HWMON)) {
		line6pcm->prev_fbuf =
		    kmalloc(LINE6_ISO_PACKETS * line6pcm->max_packet_size,
			    GFP_KERNEL);

		if (!line6pcm->prev_fbuf) {
			dev_err(line6pcm->line6->ifcdev,
				"cannot malloc monitor buffer\n");
			return -ENOMEM;
		}
	}
#else
	line6pcm->prev_fbuf = NULL;
#endif

	if (((flags_old & MASK_CAPTURE) == 0) &&
	    ((flags_new & MASK_CAPTURE) != 0)) {
		/*
		   Waiting for completion of active URBs in the stop handler is
		   a bug, we therefore report an error if capturing is restarted
		   too soon.
		 */
		if (line6pcm->active_urb_in | line6pcm->unlink_urb_in)
			return -EBUSY;

		line6pcm->buffer_in =
		    kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
			    line6pcm->max_packet_size, GFP_KERNEL);

		if (!line6pcm->buffer_in) {
			dev_err(line6pcm->line6->ifcdev,
				"cannot malloc capture buffer\n");
			return -ENOMEM;
		}

		line6pcm->count_in = 0;
		line6pcm->prev_fsize = 0;
		err = line6_submit_audio_in_all_urbs(line6pcm);

		if (err < 0) {
			__sync_fetch_and_and(&line6pcm->flags, ~channels);
			return err;
		}
	}

	if (((flags_old & MASK_PLAYBACK) == 0) &&
	    ((flags_new & MASK_PLAYBACK) != 0)) {
		/*
		   See comment above regarding PCM restart.
		 */
		if (line6pcm->active_urb_out | line6pcm->unlink_urb_out)
			return -EBUSY;

		line6pcm->buffer_out =
		    kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
			    line6pcm->max_packet_size, GFP_KERNEL);

		if (!line6pcm->buffer_out) {
			dev_err(line6pcm->line6->ifcdev,
				"cannot malloc playback buffer\n");
			return -ENOMEM;
		}

		line6pcm->count_out = 0;
		err = line6_submit_audio_out_all_urbs(line6pcm);

		if (err < 0) {
			__sync_fetch_and_and(&line6pcm->flags, ~channels);
			return err;
		}
	}

	return 0;
}