Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 288980
b: refs/heads/master
c: 0ca5488
h: refs/heads/master
v: v3
  • Loading branch information
Markus Grabner authored and Greg Kroah-Hartman committed Feb 9, 2012
1 parent 0463110 commit 0fb28e5
Show file tree
Hide file tree
Showing 10 changed files with 255 additions and 194 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 12177acdecfcb538b86590036a56fc47b443e135
refs/heads/master: 0ca54888060135806d5567f47a6ad54be5297b34
54 changes: 15 additions & 39 deletions trunk/drivers/staging/line6/capture.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ void line6_unlink_audio_in_urbs(struct snd_line6_pcm *line6pcm)
Wait until unlinking of all currently active capture URBs has been
finished.
*/
static void wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm)
void line6_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm)
{
int timeout = HZ;
unsigned int i;
Expand All @@ -134,7 +134,7 @@ static void wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm)
void line6_unlink_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm)
{
line6_unlink_audio_in_urbs(line6pcm);
wait_clear_audio_in_urbs(line6pcm);
line6_wait_clear_audio_in_urbs(line6pcm);
}

/*
Expand Down Expand Up @@ -193,25 +193,6 @@ void line6_capture_check_period(struct snd_line6_pcm *line6pcm, int length)
}
}

int line6_alloc_capture_buffer(struct snd_line6_pcm *line6pcm)
{
/* We may be invoked multiple times in a row so allocate once only */
if (line6pcm->buffer_in)
return 0;

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;
}

return 0;
}

void line6_free_capture_buffer(struct snd_line6_pcm *line6pcm)
{
kfree(line6pcm->buffer_in);
Expand Down Expand Up @@ -273,9 +254,9 @@ static void audio_in_callback(struct urb *urb)
line6pcm->prev_fsize = fsize;

#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
if (!(line6pcm->flags & MASK_PCM_IMPULSE))
if (!(line6pcm->flags & LINE6_BITS_PCM_IMPULSE))
#endif
if (test_bit(BIT_PCM_ALSA_CAPTURE, &line6pcm->flags)
if (test_bit(LINE6_INDEX_PCM_ALSA_CAPTURE_STREAM, &line6pcm->flags)
&& (fsize > 0))
line6_capture_copy(line6pcm, fbuf, fsize);
}
Expand All @@ -291,9 +272,9 @@ static void audio_in_callback(struct urb *urb)
submit_audio_in_urb(line6pcm);

#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
if (!(line6pcm->flags & MASK_PCM_IMPULSE))
if (!(line6pcm->flags & LINE6_BITS_PCM_IMPULSE))
#endif
if (test_bit(BIT_PCM_ALSA_CAPTURE, &line6pcm->flags))
if (test_bit(LINE6_INDEX_PCM_ALSA_CAPTURE_STREAM, &line6pcm->flags))
line6_capture_check_period(line6pcm, length);
}
}
Expand Down Expand Up @@ -341,17 +322,17 @@ static int snd_line6_capture_hw_params(struct snd_pcm_substream *substream,
}
/* -- [FD] end */

if ((line6pcm->flags & MASK_CAPTURE) == 0) {
ret = line6_alloc_capture_buffer(line6pcm);
ret = line6_pcm_acquire(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER);

if (ret < 0)
return ret;
}
if (ret < 0)
return ret;

ret = snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(hw_params));
if (ret < 0)
if (ret < 0) {
line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER);
return ret;
}

line6pcm->period_in = params_period_bytes(hw_params);
return 0;
Expand All @@ -361,12 +342,7 @@ static int snd_line6_capture_hw_params(struct snd_pcm_substream *substream,
static int snd_line6_capture_hw_free(struct snd_pcm_substream *substream)
{
struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);

if ((line6pcm->flags & MASK_CAPTURE) == 0) {
line6_unlink_wait_clear_audio_in_urbs(line6pcm);
line6_free_capture_buffer(line6pcm);
}

line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER);
return snd_pcm_lib_free_pages(substream);
}

Expand All @@ -380,7 +356,7 @@ int snd_line6_capture_trigger(struct snd_line6_pcm *line6pcm, int cmd)
#ifdef CONFIG_PM
case SNDRV_PCM_TRIGGER_RESUME:
#endif
err = line6_pcm_start(line6pcm, MASK_PCM_ALSA_CAPTURE);
err = line6_pcm_acquire(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_STREAM);

if (err < 0)
return err;
Expand All @@ -391,7 +367,7 @@ int snd_line6_capture_trigger(struct snd_line6_pcm *line6pcm, int cmd)
#ifdef CONFIG_PM
case SNDRV_PCM_TRIGGER_SUSPEND:
#endif
err = line6_pcm_stop(line6pcm, MASK_PCM_ALSA_CAPTURE);
err = line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_STREAM);

if (err < 0)
return err;
Expand Down
2 changes: 1 addition & 1 deletion trunk/drivers/staging/line6/capture.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

extern struct snd_pcm_ops snd_line6_capture_ops;

extern int line6_alloc_capture_buffer(struct snd_line6_pcm *line6pcm);
extern void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf,
int fsize);
extern void line6_capture_check_period(struct snd_line6_pcm *line6pcm,
Expand All @@ -30,6 +29,7 @@ extern int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm);
extern void line6_unlink_audio_in_urbs(struct snd_line6_pcm *line6pcm);
extern void line6_unlink_wait_clear_audio_in_urbs(struct snd_line6_pcm
*line6pcm);
extern void line6_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm);
extern int snd_line6_capture_trigger(struct snd_line6_pcm *line6pcm, int cmd);

#endif
2 changes: 1 addition & 1 deletion trunk/drivers/staging/line6/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -1346,7 +1346,7 @@ static void __exit line6_exit(void)
if (line6pcm == NULL)
continue;

line6_pcm_stop(line6pcm, ~0);
line6_pcm_release(line6pcm, ~0);
}

usb_deregister(&line6_driver);
Expand Down
109 changes: 73 additions & 36 deletions trunk/drivers/staging/line6/pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ static ssize_t pcm_set_impulse_volume(struct device *dev,
line6pcm->impulse_volume = value;

if (value > 0)
line6_pcm_start(line6pcm, MASK_PCM_IMPULSE);
line6_pcm_acquire(line6pcm, LINE6_BITS_PCM_IMPULSE);
else
line6_pcm_stop(line6pcm, MASK_PCM_IMPULSE);
line6_pcm_release(line6pcm, LINE6_BITS_PCM_IMPULSE);

return count;
}
Expand Down Expand Up @@ -92,85 +92,122 @@ static bool test_flags(unsigned long flags0, unsigned long flags1,
return ((flags0 & mask) == 0) && ((flags1 & mask) != 0);
}

int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels)
int line6_pcm_acquire(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;
unsigned long flags_final = flags_old;
int err = 0;

line6pcm->prev_fbuf = NULL;

if (test_flags(flags_old, flags_new, MASK_CAPTURE)) {
if (test_flags(flags_old, flags_new, LINE6_BITS_CAPTURE_BUFFER)) {
/* We may be 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) {
dev_err(line6pcm->line6->ifcdev,
"cannot malloc capture buffer\n");
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)
if (line6pcm->active_urb_in | line6pcm->unlink_urb_in) {
dev_err(line6pcm->line6->ifcdev, "Device not yet ready\n");
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;
goto pcm_acquire_error;

flags_final |= channels & LINE6_BITS_CAPTURE_STREAM;
}

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 (test_flags(flags_old, flags_new, LINE6_BITS_PLAYBACK_BUFFER)) {
/* We may be 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) {
dev_err(line6pcm->line6->ifcdev,
"cannot malloc playback buffer\n");
err = -ENOMEM;
goto pcm_acquire_error;
}

if (!(flags_new & MASK_PCM_ALSA_PLAYBACK)) {
err = line6_alloc_playback_buffer(line6pcm);
flags_final |= channels & LINE6_BITS_PLAYBACK_BUFFER;
}
}

if (err < 0)
goto pcm_start_error;
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_start_error;
goto pcm_acquire_error;

flags_final |= channels & LINE6_BITS_PLAYBACK_STREAM;
}

return 0;

pcm_start_error:
__sync_fetch_and_and(&line6pcm->flags, ~channels);
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;
}

int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels)
int line6_pcm_release(struct snd_line6_pcm *line6pcm, int channels)
{
unsigned long flags_old =
__sync_fetch_and_and(&line6pcm->flags, ~channels);
unsigned long flags_new = flags_old & ~channels;

if (test_flags(flags_new, flags_old, MASK_CAPTURE)) {
if (test_flags(flags_new, flags_old, LINE6_BITS_CAPTURE_STREAM))
line6_unlink_audio_in_urbs(line6pcm);

if (!(flags_old & MASK_PCM_ALSA_CAPTURE))
line6_free_capture_buffer(line6pcm);
if (test_flags(flags_new, flags_old, LINE6_BITS_CAPTURE_BUFFER)) {
line6_wait_clear_audio_in_urbs(line6pcm);
line6_free_capture_buffer(line6pcm);
}

if (test_flags(flags_new, flags_old, MASK_PLAYBACK)) {
if (test_flags(flags_new, flags_old, LINE6_BITS_PLAYBACK_STREAM))
line6_unlink_audio_out_urbs(line6pcm);

if (!(flags_old & MASK_PCM_ALSA_PLAYBACK))
line6_free_playback_buffer(line6pcm);
if (test_flags(flags_new, flags_old, LINE6_BITS_PLAYBACK_BUFFER)) {
line6_wait_clear_audio_out_urbs(line6pcm);
line6_free_playback_buffer(line6pcm);
}

return 0;
Expand All @@ -185,7 +222,7 @@ int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd)
unsigned long flags;

spin_lock_irqsave(&line6pcm->lock_trigger, flags);
clear_bit(BIT_PREPARED, &line6pcm->flags);
clear_bit(LINE6_INDEX_PREPARED, &line6pcm->flags);

snd_pcm_group_for_each_entry(s, substream) {
switch (s->stream) {
Expand Down Expand Up @@ -498,13 +535,13 @@ int snd_line6_prepare(struct snd_pcm_substream *substream)

switch (substream->stream) {
case SNDRV_PCM_STREAM_PLAYBACK:
if ((line6pcm->flags & MASK_PLAYBACK) == 0)
if ((line6pcm->flags & LINE6_BITS_PLAYBACK_STREAM) == 0)
line6_unlink_wait_clear_audio_out_urbs(line6pcm);

break;

case SNDRV_PCM_STREAM_CAPTURE:
if ((line6pcm->flags & MASK_CAPTURE) == 0)
if ((line6pcm->flags & LINE6_BITS_CAPTURE_STREAM) == 0)
line6_unlink_wait_clear_audio_in_urbs(line6pcm);

break;
Expand All @@ -513,7 +550,7 @@ int snd_line6_prepare(struct snd_pcm_substream *substream)
MISSING_CASE;
}

if (!test_and_set_bit(BIT_PREPARED, &line6pcm->flags)) {
if (!test_and_set_bit(LINE6_INDEX_PREPARED, &line6pcm->flags)) {
line6pcm->count_out = 0;
line6pcm->pos_out = 0;
line6pcm->pos_out_done = 0;
Expand Down
Loading

0 comments on commit 0fb28e5

Please sign in to comment.