aboutsummaryrefslogtreecommitdiff
path: root/sound/usb/6fire/pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb/6fire/pcm.c')
-rw-r--r--sound/usb/6fire/pcm.c114
1 files changed, 81 insertions, 33 deletions
diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c
index e2ca12fe92e..ba40489b2de 100644
--- a/sound/usb/6fire/pcm.c
+++ b/sound/usb/6fire/pcm.c
@@ -79,32 +79,35 @@ static int usb6fire_pcm_set_rate(struct pcm_runtime *rt)
ctrl_rt->usb_streaming = false;
ret = ctrl_rt->update_streaming(ctrl_rt);
if (ret < 0) {
- snd_printk(KERN_ERR PREFIX "error stopping streaming while "
- "setting samplerate %d.\n", rates[rt->rate]);
+ dev_err(&rt->chip->dev->dev,
+ "error stopping streaming while setting samplerate %d.\n",
+ rates[rt->rate]);
return ret;
}
ret = ctrl_rt->set_rate(ctrl_rt, rt->rate);
if (ret < 0) {
- snd_printk(KERN_ERR PREFIX "error setting samplerate %d.\n",
- rates[rt->rate]);
+ dev_err(&rt->chip->dev->dev,
+ "error setting samplerate %d.\n",
+ rates[rt->rate]);
return ret;
}
ret = ctrl_rt->set_channels(ctrl_rt, OUT_N_CHANNELS, IN_N_CHANNELS,
false, false);
if (ret < 0) {
- snd_printk(KERN_ERR PREFIX "error initializing channels "
- "while setting samplerate %d.\n",
- rates[rt->rate]);
+ dev_err(&rt->chip->dev->dev,
+ "error initializing channels while setting samplerate %d.\n",
+ rates[rt->rate]);
return ret;
}
ctrl_rt->usb_streaming = true;
ret = ctrl_rt->update_streaming(ctrl_rt);
if (ret < 0) {
- snd_printk(KERN_ERR PREFIX "error starting streaming while "
- "setting samplerate %d.\n", rates[rt->rate]);
+ dev_err(&rt->chip->dev->dev,
+ "error starting streaming while setting samplerate %d.\n",
+ rates[rt->rate]);
return ret;
}
@@ -124,7 +127,7 @@ static struct pcm_substream *usb6fire_pcm_get_substream(
return &rt->playback;
else if (alsa_sub->stream == SNDRV_PCM_STREAM_CAPTURE)
return &rt->capture;
- snd_printk(KERN_ERR PREFIX "error getting pcm substream slot.\n");
+ dev_err(&rt->chip->dev->dev, "error getting pcm substream slot.\n");
return NULL;
}
@@ -257,7 +260,7 @@ static void usb6fire_pcm_playback(struct pcm_substream *sub,
else if (alsa_rt->format == SNDRV_PCM_FORMAT_S24_LE)
dest = (u32 *) (urb->buffer);
else {
- snd_printk(KERN_ERR PREFIX "Unknown sample format.");
+ dev_err(&rt->chip->dev->dev, "Unknown sample format.");
return;
}
@@ -307,8 +310,8 @@ static void usb6fire_pcm_in_urb_handler(struct urb *usb_urb)
}
if (rt->stream_state == STREAM_DISABLED) {
- snd_printk(KERN_ERR PREFIX "internal error: "
- "stream disabled in in-urb handler.\n");
+ dev_err(&rt->chip->dev->dev,
+ "internal error: stream disabled in in-urb handler.\n");
return;
}
@@ -410,7 +413,7 @@ static int usb6fire_pcm_open(struct snd_pcm_substream *alsa_sub)
if (!sub) {
mutex_unlock(&rt->stream_mutex);
- snd_printk(KERN_ERR PREFIX "invalid stream type.\n");
+ dev_err(&rt->chip->dev->dev, "invalid stream type.\n");
return -EINVAL;
}
@@ -450,13 +453,13 @@ static int usb6fire_pcm_close(struct snd_pcm_substream *alsa_sub)
static int usb6fire_pcm_hw_params(struct snd_pcm_substream *alsa_sub,
struct snd_pcm_hw_params *hw_params)
{
- return snd_pcm_lib_malloc_pages(alsa_sub,
- params_buffer_bytes(hw_params));
+ return snd_pcm_lib_alloc_vmalloc_buffer(alsa_sub,
+ params_buffer_bytes(hw_params));
}
static int usb6fire_pcm_hw_free(struct snd_pcm_substream *alsa_sub)
{
- return snd_pcm_lib_free_pages(alsa_sub);
+ return snd_pcm_lib_free_vmalloc_buffer(alsa_sub);
}
static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub)
@@ -481,8 +484,9 @@ static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub)
break;
if (rt->rate == ARRAY_SIZE(rates)) {
mutex_unlock(&rt->stream_mutex);
- snd_printk("invalid rate %d in prepare.\n",
- alsa_rt->rate);
+ dev_err(&rt->chip->dev->dev,
+ "invalid rate %d in prepare.\n",
+ alsa_rt->rate);
return -EINVAL;
}
@@ -494,8 +498,8 @@ static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub)
ret = usb6fire_pcm_stream_start(rt);
if (ret) {
mutex_unlock(&rt->stream_mutex);
- snd_printk(KERN_ERR PREFIX
- "could not start pcm stream.\n");
+ dev_err(&rt->chip->dev->dev,
+ "could not start pcm stream.\n");
return ret;
}
}
@@ -543,7 +547,7 @@ static snd_pcm_uframes_t usb6fire_pcm_pointer(
snd_pcm_uframes_t ret;
if (rt->panic || !sub)
- return SNDRV_PCM_STATE_XRUN;
+ return SNDRV_PCM_POS_XRUN;
spin_lock_irqsave(&sub->lock, flags);
ret = sub->dma_off;
@@ -560,6 +564,8 @@ static struct snd_pcm_ops pcm_ops = {
.prepare = usb6fire_pcm_prepare,
.trigger = usb6fire_pcm_trigger,
.pointer = usb6fire_pcm_pointer,
+ .page = snd_pcm_lib_get_vmalloc_page,
+ .mmap = snd_pcm_lib_mmap_vmalloc,
};
static void usb6fire_pcm_init_urb(struct pcm_urb *urb,
@@ -575,12 +581,38 @@ static void usb6fire_pcm_init_urb(struct pcm_urb *urb,
urb->instance.pipe = in ? usb_rcvisocpipe(chip->dev, ep)
: usb_sndisocpipe(chip->dev, ep);
urb->instance.interval = 1;
- urb->instance.transfer_flags = URB_ISO_ASAP;
urb->instance.complete = handler;
urb->instance.context = urb;
urb->instance.number_of_packets = PCM_N_PACKETS_PER_URB;
}
+static int usb6fire_pcm_buffers_init(struct pcm_runtime *rt)
+{
+ int i;
+
+ for (i = 0; i < PCM_N_URBS; i++) {
+ rt->out_urbs[i].buffer = kzalloc(PCM_N_PACKETS_PER_URB
+ * PCM_MAX_PACKET_SIZE, GFP_KERNEL);
+ if (!rt->out_urbs[i].buffer)
+ return -ENOMEM;
+ rt->in_urbs[i].buffer = kzalloc(PCM_N_PACKETS_PER_URB
+ * PCM_MAX_PACKET_SIZE, GFP_KERNEL);
+ if (!rt->in_urbs[i].buffer)
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static void usb6fire_pcm_buffers_destroy(struct pcm_runtime *rt)
+{
+ int i;
+
+ for (i = 0; i < PCM_N_URBS; i++) {
+ kfree(rt->out_urbs[i].buffer);
+ kfree(rt->in_urbs[i].buffer);
+ }
+}
+
int usb6fire_pcm_init(struct sfire_chip *chip)
{
int i;
@@ -592,6 +624,13 @@ int usb6fire_pcm_init(struct sfire_chip *chip)
if (!rt)
return -ENOMEM;
+ ret = usb6fire_pcm_buffers_init(rt);
+ if (ret) {
+ usb6fire_pcm_buffers_destroy(rt);
+ kfree(rt);
+ return ret;
+ }
+
rt->chip = chip;
rt->stream_state = STREAM_DISABLED;
rt->rate = ARRAY_SIZE(rates);
@@ -613,8 +652,9 @@ int usb6fire_pcm_init(struct sfire_chip *chip)
ret = snd_pcm_new(chip->card, "DMX6FireUSB", 0, 1, 1, &pcm);
if (ret < 0) {
+ usb6fire_pcm_buffers_destroy(rt);
kfree(rt);
- snd_printk(KERN_ERR PREFIX "cannot create pcm instance.\n");
+ dev_err(&chip->dev->dev, "cannot create pcm instance.\n");
return ret;
}
@@ -623,14 +663,11 @@ int usb6fire_pcm_init(struct sfire_chip *chip)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_ops);
- ret = snd_pcm_lib_preallocate_pages_for_all(pcm,
- SNDRV_DMA_TYPE_CONTINUOUS,
- snd_dma_continuous_data(GFP_KERNEL),
- MAX_BUFSIZE, MAX_BUFSIZE);
if (ret) {
+ usb6fire_pcm_buffers_destroy(rt);
kfree(rt);
- snd_printk(KERN_ERR PREFIX
- "error preallocating pcm buffers.\n");
+ dev_err(&chip->dev->dev,
+ "error preallocating pcm buffers.\n");
return ret;
}
rt->instance = pcm;
@@ -642,17 +679,25 @@ int usb6fire_pcm_init(struct sfire_chip *chip)
void usb6fire_pcm_abort(struct sfire_chip *chip)
{
struct pcm_runtime *rt = chip->pcm;
+ unsigned long flags;
int i;
if (rt) {
rt->panic = true;
- if (rt->playback.instance)
+ if (rt->playback.instance) {
+ snd_pcm_stream_lock_irqsave(rt->playback.instance, flags);
snd_pcm_stop(rt->playback.instance,
SNDRV_PCM_STATE_XRUN);
- if (rt->capture.instance)
+ snd_pcm_stream_unlock_irqrestore(rt->playback.instance, flags);
+ }
+
+ if (rt->capture.instance) {
+ snd_pcm_stream_lock_irqsave(rt->capture.instance, flags);
snd_pcm_stop(rt->capture.instance,
SNDRV_PCM_STATE_XRUN);
+ snd_pcm_stream_unlock_irqrestore(rt->capture.instance, flags);
+ }
for (i = 0; i < PCM_N_URBS; i++) {
usb_poison_urb(&rt->in_urbs[i].instance);
@@ -664,6 +709,9 @@ void usb6fire_pcm_abort(struct sfire_chip *chip)
void usb6fire_pcm_destroy(struct sfire_chip *chip)
{
- kfree(chip->pcm);
+ struct pcm_runtime *rt = chip->pcm;
+
+ usb6fire_pcm_buffers_destroy(rt);
+ kfree(rt);
chip->pcm = NULL;
}