aboutsummaryrefslogtreecommitdiff
path: root/drivers/staging/line6/playback.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/line6/playback.c')
-rw-r--r--drivers/staging/line6/playback.c100
1 files changed, 41 insertions, 59 deletions
diff --git a/drivers/staging/line6/playback.c b/drivers/staging/line6/playback.c
index 4152db2328b..2ca8900e68c 100644
--- a/drivers/staging/line6/playback.c
+++ b/drivers/staging/line6/playback.c
@@ -34,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);
@@ -43,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;
@@ -116,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);
@@ -166,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;
@@ -185,7 +190,7 @@ 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;
}
@@ -196,8 +201,8 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
urb_out->transfer_buffer_length = urb_size;
urb_out->context = line6pcm;
- 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;
@@ -207,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) {
@@ -218,7 +224,8 @@ 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 {
memcpy(urb_out->transfer_buffer,
runtime->dma_area +
@@ -238,24 +245,25 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
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);
@@ -263,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);
@@ -312,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);
}
}
@@ -319,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;
@@ -348,26 +349,7 @@ 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);
-}
-
-int line6_alloc_playback_buffer(struct snd_line6_pcm *line6pcm)
-{
- /* We may be invoked multiple times in a row so allocate once only */
- if (line6pcm->buffer_out)
- return 0;
-
- 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;
- }
-
- return 0;
+ line6_wait_clear_audio_out_urbs(line6pcm);
}
void line6_free_playback_buffer(struct snd_line6_pcm *line6pcm)
@@ -383,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);
@@ -407,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;
@@ -432,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;
@@ -484,17 +467,17 @@ static int snd_line6_playback_hw_params(struct snd_pcm_substream *substream,
}
/* -- [FD] end */
- if ((line6pcm->flags & MASK_PLAYBACK) == 0) {
- ret = line6_alloc_playback_buffer(line6pcm);
+ ret = line6_pcm_acquire(line6pcm, LINE6_BIT_PCM_ALSA_PLAYBACK_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_PLAYBACK_BUFFER);
return ret;
+ }
line6pcm->period_out = params_period_bytes(hw_params);
return 0;
@@ -505,11 +488,7 @@ static int snd_line6_playback_hw_free(struct snd_pcm_substream *substream)
{
struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
- if ((line6pcm->flags & MASK_PLAYBACK) == 0) {
- line6_unlink_wait_clear_audio_out_urbs(line6pcm);
- line6_free_playback_buffer(line6pcm);
- }
-
+ line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER);
return snd_pcm_lib_free_pages(substream);
}
@@ -523,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;
@@ -534,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;
@@ -542,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:
@@ -561,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;
}