summaryrefslogtreecommitdiff
path: root/sound/usb/caiaq/audio.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb/caiaq/audio.c')
-rw-r--r--sound/usb/caiaq/audio.c117
1 files changed, 40 insertions, 77 deletions
diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c
index 7103b0908d13..95d425dd9d70 100644
--- a/sound/usb/caiaq/audio.c
+++ b/sound/usb/caiaq/audio.c
@@ -1,19 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2006-2008 Daniel Mack, Karsten Wiese
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/device.h>
@@ -43,7 +30,7 @@
#define MAKE_CHECKBYTE(cdev,stream,i) \
(stream << 1) | (~(i / (cdev->n_streams * BYTES_PER_SAMPLE_USB)) & 1)
-static struct snd_pcm_hardware snd_usb_caiaq_pcm_hardware = {
+static const struct snd_pcm_hardware snd_usb_caiaq_pcm_hardware = {
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER),
.formats = SNDRV_PCM_FMTBIT_S24_3BE,
@@ -64,29 +51,24 @@ static void
activate_substream(struct snd_usb_caiaqdev *cdev,
struct snd_pcm_substream *sub)
{
- spin_lock(&cdev->spinlock);
+ guard(spinlock)(&cdev->spinlock);
if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
cdev->sub_playback[sub->number] = sub;
else
cdev->sub_capture[sub->number] = sub;
-
- spin_unlock(&cdev->spinlock);
}
static void
deactivate_substream(struct snd_usb_caiaqdev *cdev,
struct snd_pcm_substream *sub)
{
- unsigned long flags;
- spin_lock_irqsave(&cdev->spinlock, flags);
+ guard(spinlock_irqsave)(&cdev->spinlock);
if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
cdev->sub_playback[sub->number] = NULL;
else
cdev->sub_capture[sub->number] = NULL;
-
- spin_unlock_irqrestore(&cdev->spinlock, flags);
}
static int
@@ -180,31 +162,16 @@ static int snd_usb_caiaq_substream_close(struct snd_pcm_substream *substream)
return 0;
}
-static int snd_usb_caiaq_pcm_hw_params(struct snd_pcm_substream *sub,
- struct snd_pcm_hw_params *hw_params)
-{
- return snd_pcm_lib_alloc_vmalloc_buffer(sub,
- params_buffer_bytes(hw_params));
-}
-
static int snd_usb_caiaq_pcm_hw_free(struct snd_pcm_substream *sub)
{
struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(sub);
deactivate_substream(cdev, sub);
- return snd_pcm_lib_free_vmalloc_buffer(sub);
+ return 0;
}
-/* this should probably go upstream */
-#if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 12
-#error "Change this table"
-#endif
-
-static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100,
- 48000, 64000, 88200, 96000, 176400, 192000 };
-
static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
{
- int bytes_per_sample, bpp, ret, i;
+ int bytes_per_sample, bpp, ret;
int index = substream->number;
struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -253,10 +220,7 @@ static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
/* the first client that opens a stream defines the sample rate
* setting for all subsequent calls, until the last client closed. */
- for (i=0; i < ARRAY_SIZE(rates); i++)
- if (runtime->rate == rates[i])
- cdev->pcm_info.rates = 1 << i;
-
+ cdev->pcm_info.rates = snd_pcm_rate_to_rate_bit(runtime->rate);
snd_pcm_limit_hw_rates(runtime);
bytes_per_sample = BYTES_PER_SAMPLE;
@@ -316,39 +280,28 @@ snd_usb_caiaq_pcm_pointer(struct snd_pcm_substream *sub)
{
int index = sub->number;
struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(sub);
- snd_pcm_uframes_t ptr;
- spin_lock(&cdev->spinlock);
+ guard(spinlock)(&cdev->spinlock);
- if (cdev->input_panic || cdev->output_panic) {
- ptr = SNDRV_PCM_POS_XRUN;
- goto unlock;
- }
+ if (cdev->input_panic || cdev->output_panic)
+ return SNDRV_PCM_POS_XRUN;
if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
- ptr = bytes_to_frames(sub->runtime,
- cdev->audio_out_buf_pos[index]);
+ return bytes_to_frames(sub->runtime,
+ cdev->audio_out_buf_pos[index]);
else
- ptr = bytes_to_frames(sub->runtime,
- cdev->audio_in_buf_pos[index]);
-
-unlock:
- spin_unlock(&cdev->spinlock);
- return ptr;
+ return bytes_to_frames(sub->runtime,
+ cdev->audio_in_buf_pos[index]);
}
/* operators for both playback and capture */
-static struct snd_pcm_ops snd_usb_caiaq_ops = {
+static const struct snd_pcm_ops snd_usb_caiaq_ops = {
.open = snd_usb_caiaq_substream_open,
.close = snd_usb_caiaq_substream_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = snd_usb_caiaq_pcm_hw_params,
.hw_free = snd_usb_caiaq_pcm_hw_free,
.prepare = snd_usb_caiaq_pcm_prepare,
.trigger = snd_usb_caiaq_pcm_trigger,
.pointer = snd_usb_caiaq_pcm_pointer,
- .page = snd_pcm_lib_get_vmalloc_page,
- .mmap = snd_pcm_lib_mmap_vmalloc,
};
static void check_for_elapsed_periods(struct snd_usb_caiaqdev *cdev,
@@ -672,10 +625,10 @@ static void read_completed(struct urb *urb)
offset += len;
if (len > 0) {
- spin_lock(&cdev->spinlock);
- fill_out_urb(cdev, out, &out->iso_frame_desc[outframe]);
- read_in_urb(cdev, urb, &urb->iso_frame_desc[frame]);
- spin_unlock(&cdev->spinlock);
+ scoped_guard(spinlock_irqsave, &cdev->spinlock) {
+ fill_out_urb(cdev, out, &out->iso_frame_desc[outframe]);
+ read_in_urb(cdev, urb, &urb->iso_frame_desc[frame]);
+ }
check_for_elapsed_periods(cdev, cdev->sub_playback);
check_for_elapsed_periods(cdev, cdev->sub_capture);
send_it = 1;
@@ -722,16 +675,14 @@ static struct urb **alloc_urbs(struct snd_usb_caiaqdev *cdev, int dir, int *ret)
int i, frame;
struct urb **urbs;
struct usb_device *usb_dev = cdev->chip.dev;
- struct device *dev = caiaqdev_to_dev(cdev);
unsigned int pipe;
pipe = (dir == SNDRV_PCM_STREAM_PLAYBACK) ?
usb_sndisocpipe(usb_dev, ENDPOINT_PLAYBACK) :
usb_rcvisocpipe(usb_dev, ENDPOINT_CAPTURE);
- urbs = kmalloc(N_URBS * sizeof(*urbs), GFP_KERNEL);
+ urbs = kmalloc_array(N_URBS, sizeof(*urbs), GFP_KERNEL);
if (!urbs) {
- dev_err(dev, "unable to kmalloc() urbs, OOM!?\n");
*ret = -ENOMEM;
return NULL;
}
@@ -739,15 +690,14 @@ static struct urb **alloc_urbs(struct snd_usb_caiaqdev *cdev, int dir, int *ret)
for (i = 0; i < N_URBS; i++) {
urbs[i] = usb_alloc_urb(FRAMES_PER_URB, GFP_KERNEL);
if (!urbs[i]) {
- dev_err(dev, "unable to usb_alloc_urb(), OOM!?\n");
*ret = -ENOMEM;
return urbs;
}
urbs[i]->transfer_buffer =
- kmalloc(FRAMES_PER_URB * BYTES_PER_FRAME, GFP_KERNEL);
+ kmalloc_array(BYTES_PER_FRAME, FRAMES_PER_URB,
+ GFP_KERNEL);
if (!urbs[i]->transfer_buffer) {
- dev_err(dev, "unable to kmalloc() transfer buffer, OOM!?\n");
*ret = -ENOMEM;
return urbs;
}
@@ -816,6 +766,11 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *cdev)
return -EINVAL;
}
+ if (cdev->n_streams < 1) {
+ dev_err(dev, "bogus number of streams: %d\n", cdev->n_streams);
+ return -EINVAL;
+ }
+
ret = snd_pcm_new(cdev->chip.card, cdev->product_name, 0,
cdev->n_audio_out, cdev->n_audio_in, &cdev->pcm);
@@ -825,7 +780,7 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *cdev)
}
cdev->pcm->private_data = cdev;
- strlcpy(cdev->pcm->name, cdev->product_name, sizeof(cdev->pcm->name));
+ strscpy(cdev->pcm->name, cdev->product_name, sizeof(cdev->pcm->name));
memset(cdev->sub_playback, 0, sizeof(cdev->sub_playback));
memset(cdev->sub_capture, 0, sizeof(cdev->sub_capture));
@@ -841,7 +796,7 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *cdev)
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_SESSIONIO):
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_GUITARRIGMOBILE):
cdev->samplerates |= SNDRV_PCM_RATE_192000;
- /* fall thru */
+ fallthrough;
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO2DJ):
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ):
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ):
@@ -854,9 +809,11 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *cdev)
&snd_usb_caiaq_ops);
snd_pcm_set_ops(cdev->pcm, SNDRV_PCM_STREAM_CAPTURE,
&snd_usb_caiaq_ops);
+ snd_pcm_set_managed_buffer_all(cdev->pcm, SNDRV_DMA_TYPE_VMALLOC,
+ NULL, 0, 0);
cdev->data_cb_info =
- kmalloc(sizeof(struct snd_usb_caiaq_cb_info) * N_URBS,
+ kmalloc_array(N_URBS, sizeof(struct snd_usb_caiaq_cb_info),
GFP_KERNEL);
if (!cdev->data_cb_info)
@@ -888,14 +845,20 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *cdev)
return 0;
}
-void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *cdev)
+void snd_usb_caiaq_audio_disconnect(struct snd_usb_caiaqdev *cdev)
{
struct device *dev = caiaqdev_to_dev(cdev);
dev_dbg(dev, "%s(%p)\n", __func__, cdev);
stream_stop(cdev);
+}
+
+void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *cdev)
+{
+ struct device *dev = caiaqdev_to_dev(cdev);
+
+ dev_dbg(dev, "%s(%p)\n", __func__, cdev);
free_urbs(cdev->data_urbs_in);
free_urbs(cdev->data_urbs_out);
kfree(cdev->data_cb_info);
}
-