diff options
Diffstat (limited to 'drivers/staging/line6/playback.c')
| -rw-r--r-- | drivers/staging/line6/playback.c | 97 |
1 files changed, 54 insertions, 43 deletions
diff --git a/drivers/staging/line6/playback.c b/drivers/staging/line6/playback.c index 29940fd1671..2ca8900e68c 100644 --- a/drivers/staging/line6/playback.c +++ b/drivers/staging/line6/playback.c @@ -9,6 +9,7 @@ * */ +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -33,6 +34,7 @@ static void change_volume(struct urb *urb_out, int volume[], if (bytes_per_frame == 4) { short *p, *buf_end; + p = (short *)urb_out->transfer_buffer; buf_end = p + urb_out->transfer_buffer_length / sizeof(*p); @@ -42,11 +44,13 @@ static void change_volume(struct urb *urb_out, int volume[], } } else if (bytes_per_frame == 6) { unsigned char *p, *buf_end; + p = (unsigned char *)urb_out->transfer_buffer; buf_end = p + urb_out->transfer_buffer_length; for (; p < buf_end; p += 3) { int val; + val = p[0] + (p[1] << 8) + ((signed char)p[2] << 16); val = (val * volume[chn & 1]) >> 8; p[0] = val; @@ -115,6 +119,7 @@ static void add_monitor_signal(struct urb *urb_out, unsigned char *signal, if (bytes_per_frame == 4) { short *pi, *po, *buf_end; + pi = (short *)signal; po = (short *)urb_out->transfer_buffer; buf_end = po + urb_out->transfer_buffer_length / sizeof(*po); @@ -165,11 +170,12 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) struct usb_iso_packet_descriptor *fout = &urb_out->iso_frame_desc[i]; - if (line6pcm->flags & MASK_CAPTURE) + if (line6pcm->flags & LINE6_BITS_CAPTURE_STREAM) fsize = line6pcm->prev_fsize; if (fsize == 0) { int n; + line6pcm->count_out += frame_increment; n = line6pcm->count_out / frame_factor; line6pcm->count_out -= n * frame_factor; @@ -184,22 +190,19 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) if (urb_size == 0) { /* can't determine URB size */ spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags); - dev_err(line6pcm->line6->ifcdev, "driver bug: urb_size = 0\n"); /* this is somewhat paranoid */ + dev_err(line6pcm->line6->ifcdev, "driver bug: urb_size = 0\n"); return -EINVAL; } urb_frames = urb_size / bytes_per_frame; urb_out->transfer_buffer = line6pcm->buffer_out + - line6pcm->max_packet_size * line6pcm->index_out; + index * LINE6_ISO_PACKETS * line6pcm->max_packet_size; urb_out->transfer_buffer_length = urb_size; urb_out->context = line6pcm; - if (++line6pcm->index_out == LINE6_ISO_BUFFERS) - line6pcm->index_out = 0; - - if (test_bit(BIT_PCM_ALSA_PLAYBACK, &line6pcm->flags) && - !test_bit(BIT_PAUSE_PLAYBACK, &line6pcm->flags)) { + if (test_bit(LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM, &line6pcm->flags) && + !test_bit(LINE6_INDEX_PAUSE_PLAYBACK, &line6pcm->flags)) { struct snd_pcm_runtime *runtime = get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK)->runtime; @@ -209,6 +212,7 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) copy the data to the temp buffer. */ int len; + len = runtime->buffer_size - line6pcm->pos_out; if (len > 0) { @@ -220,20 +224,13 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) len * bytes_per_frame, runtime->dma_area, (urb_frames - len) * bytes_per_frame); } else - dev_err(line6pcm->line6->ifcdev, "driver bug: len = %d\n", len); /* this is somewhat paranoid */ + dev_err(line6pcm->line6->ifcdev, "driver bug: len = %d\n", + len); } else { -#if LINE6_REUSE_DMA_AREA_FOR_PLAYBACK - /* set the buffer pointer */ - urb_out->transfer_buffer = - runtime->dma_area + - line6pcm->pos_out * bytes_per_frame; -#else - /* copy data */ memcpy(urb_out->transfer_buffer, runtime->dma_area + line6pcm->pos_out * bytes_per_frame, urb_out->transfer_buffer_length); -#endif } line6pcm->pos_out += urb_frames; @@ -246,26 +243,27 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) change_volume(urb_out, line6pcm->volume_playback, bytes_per_frame); - if (line6pcm->prev_fbuf != 0) { + if (line6pcm->prev_fbuf != NULL) { #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE - if (line6pcm->flags & MASK_PCM_IMPULSE) { + if (line6pcm->flags & LINE6_BITS_PCM_IMPULSE) { create_impulse_test_signal(line6pcm, urb_out, bytes_per_frame); - if (line6pcm->flags & MASK_PCM_ALSA_CAPTURE) { + if (line6pcm->flags & + LINE6_BIT_PCM_ALSA_CAPTURE_STREAM) { line6_capture_copy(line6pcm, urb_out->transfer_buffer, urb_out-> transfer_buffer_length); line6_capture_check_period(line6pcm, - urb_out->transfer_buffer_length); + urb_out->transfer_buffer_length); } } else { #endif if (! (line6pcm->line6-> properties->capabilities & LINE6_BIT_HWMON) -&& (line6pcm->flags & MASK_PLAYBACK) -&& (line6pcm->flags & MASK_CAPTURE)) + && (line6pcm->flags & LINE6_BITS_PLAYBACK_STREAM) + && (line6pcm->flags & LINE6_BITS_CAPTURE_STREAM)) add_monitor_signal(urb_out, line6pcm->prev_fbuf, line6pcm->volume_monitor, bytes_per_frame); @@ -273,15 +271,6 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) } #endif } -#ifdef CONFIG_LINE6_USB_DUMP_PCM - for (i = 0; i < LINE6_ISO_PACKETS; ++i) { - struct usb_iso_packet_descriptor *fout = - &urb_out->iso_frame_desc[i]; - line6_write_hexdump(line6pcm->line6, 'P', - urb_out->transfer_buffer + fout->offset, - fout->length); - } -#endif ret = usb_submit_urb(urb_out, GFP_ATOMIC); @@ -322,6 +311,7 @@ void line6_unlink_audio_out_urbs(struct snd_line6_pcm *line6pcm) if (test_bit(i, &line6pcm->active_urb_out)) { if (!test_and_set_bit(i, &line6pcm->unlink_urb_out)) { struct urb *u = line6pcm->urb_audio_out[i]; + usb_unlink_urb(u); } } @@ -329,9 +319,10 @@ void line6_unlink_audio_out_urbs(struct snd_line6_pcm *line6pcm) } /* - Wait until unlinking of all currently active playback URBs has been finished. + Wait until unlinking of all currently active playback URBs has been + finished. */ -static void wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm) +void line6_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm) { int timeout = HZ; unsigned int i; @@ -358,7 +349,13 @@ static void wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm) void line6_unlink_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm) { line6_unlink_audio_out_urbs(line6pcm); - wait_clear_audio_out_urbs(line6pcm); + line6_wait_clear_audio_out_urbs(line6pcm); +} + +void line6_free_playback_buffer(struct snd_line6_pcm *line6pcm) +{ + kfree(line6pcm->buffer_out); + line6pcm->buffer_out = NULL; } /* @@ -368,7 +365,6 @@ static void audio_out_callback(struct urb *urb) { int i, index, length = 0, shutdown = 0; unsigned long flags; - struct snd_line6_pcm *line6pcm = (struct snd_line6_pcm *)urb->context; struct snd_pcm_substream *substream = get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK); @@ -392,8 +388,9 @@ static void audio_out_callback(struct urb *urb) spin_lock_irqsave(&line6pcm->lock_audio_out, flags); - if (test_bit(BIT_PCM_ALSA_PLAYBACK, &line6pcm->flags)) { + if (test_bit(LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM, &line6pcm->flags)) { struct snd_pcm_runtime *runtime = substream->runtime; + line6pcm->pos_out_done += length / line6pcm->properties->bytes_per_frame; @@ -417,7 +414,8 @@ static void audio_out_callback(struct urb *urb) if (!shutdown) { submit_audio_out_urb(line6pcm); - if (test_bit(BIT_PCM_ALSA_PLAYBACK, &line6pcm->flags)) { + if (test_bit(LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM, + &line6pcm->flags)) { line6pcm->bytes_out += length; if (line6pcm->bytes_out >= line6pcm->period_out) { line6pcm->bytes_out %= line6pcm->period_out; @@ -469,10 +467,17 @@ static int snd_line6_playback_hw_params(struct snd_pcm_substream *substream, } /* -- [FD] end */ + ret = line6_pcm_acquire(line6pcm, LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER); + + 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_PLAYBACK_BUFFER); return ret; + } line6pcm->period_out = params_period_bytes(hw_params); return 0; @@ -481,6 +486,9 @@ static int snd_line6_playback_hw_params(struct snd_pcm_substream *substream, /* hw_free playback callback */ static int snd_line6_playback_hw_free(struct snd_pcm_substream *substream) { + struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); + + line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER); return snd_pcm_lib_free_pages(substream); } @@ -494,7 +502,8 @@ int snd_line6_playback_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_PLAYBACK); + err = line6_pcm_acquire(line6pcm, + LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM); if (err < 0) return err; @@ -505,7 +514,8 @@ int snd_line6_playback_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_PLAYBACK); + err = line6_pcm_release(line6pcm, + LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM); if (err < 0) return err; @@ -513,11 +523,11 @@ int snd_line6_playback_trigger(struct snd_line6_pcm *line6pcm, int cmd) break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - set_bit(BIT_PAUSE_PLAYBACK, &line6pcm->flags); + set_bit(LINE6_INDEX_PAUSE_PLAYBACK, &line6pcm->flags); break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - clear_bit(BIT_PAUSE_PLAYBACK, &line6pcm->flags); + clear_bit(LINE6_INDEX_PAUSE_PLAYBACK, &line6pcm->flags); break; default: @@ -532,6 +542,7 @@ static snd_pcm_uframes_t snd_line6_playback_pointer(struct snd_pcm_substream *substream) { struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); + return line6pcm->pos_out_done; } |
