summaryrefslogtreecommitdiff
path: root/sound/core/pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core/pcm.c')
-rw-r--r--sound/core/pcm.c142
1 files changed, 64 insertions, 78 deletions
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 9d95e3731123..283aac441fa0 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -91,9 +91,8 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
if (get_user(device, (int __user *)arg))
return -EFAULT;
- mutex_lock(&register_mutex);
- device = snd_pcm_next(card, device);
- mutex_unlock(&register_mutex);
+ scoped_guard(mutex, &register_mutex)
+ device = snd_pcm_next(card, device);
if (put_user(device, (int __user *)arg))
return -EFAULT;
return 0;
@@ -106,7 +105,6 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
struct snd_pcm *pcm;
struct snd_pcm_str *pstr;
struct snd_pcm_substream *substream;
- int err;
info = (struct snd_pcm_info __user *)arg;
if (get_user(device, &info->device))
@@ -118,35 +116,23 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
stream = array_index_nospec(stream, 2);
if (get_user(subdevice, &info->subdevice))
return -EFAULT;
- mutex_lock(&register_mutex);
+ guard(mutex)(&register_mutex);
pcm = snd_pcm_get(card, device);
- if (pcm == NULL) {
- err = -ENXIO;
- goto _error;
- }
+ if (pcm == NULL)
+ return -ENXIO;
pstr = &pcm->streams[stream];
- if (pstr->substream_count == 0) {
- err = -ENOENT;
- goto _error;
- }
- if (subdevice >= pstr->substream_count) {
- err = -ENXIO;
- goto _error;
- }
+ if (pstr->substream_count == 0)
+ return -ENOENT;
+ if (subdevice >= pstr->substream_count)
+ return -ENXIO;
for (substream = pstr->substream; substream;
substream = substream->next)
if (substream->number == (int)subdevice)
break;
- if (substream == NULL) {
- err = -ENXIO;
- goto _error;
- }
- mutex_lock(&pcm->open_mutex);
- err = snd_pcm_info_user(substream, info);
- mutex_unlock(&pcm->open_mutex);
- _error:
- mutex_unlock(&register_mutex);
- return err;
+ if (substream == NULL)
+ return -ENXIO;
+ guard(mutex)(&pcm->open_mutex);
+ return snd_pcm_info_user(substream, info);
}
case SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE:
{
@@ -211,6 +197,10 @@ static const char * const snd_pcm_format_names[] = {
FORMAT(DSD_U32_LE),
FORMAT(DSD_U16_BE),
FORMAT(DSD_U32_BE),
+ FORMAT(S20_LE),
+ FORMAT(S20_BE),
+ FORMAT(U20_LE),
+ FORMAT(U20_BE),
};
/**
@@ -221,9 +211,11 @@ static const char * const snd_pcm_format_names[] = {
*/
const char *snd_pcm_format_name(snd_pcm_format_t format)
{
- if ((__force unsigned int)format >= ARRAY_SIZE(snd_pcm_format_names))
+ unsigned int format_num = (__force unsigned int)format;
+
+ if (format_num >= ARRAY_SIZE(snd_pcm_format_names) || !snd_pcm_format_names[format_num])
return "Unknown";
- return snd_pcm_format_names[(__force unsigned int)format];
+ return snd_pcm_format_names[format_num];
}
EXPORT_SYMBOL_GPL(snd_pcm_format_name);
@@ -253,6 +245,7 @@ static const char * const snd_pcm_state_names[] = {
STATE(DRAINING),
STATE(PAUSED),
STATE(SUSPENDED),
+ STATE(DISCONNECTED),
};
static const char * const snd_pcm_access_names[] = {
@@ -265,6 +258,9 @@ static const char * const snd_pcm_access_names[] = {
static const char * const snd_pcm_subformat_names[] = {
SUBFORMAT(STD),
+ SUBFORMAT(MSBITS_MAX),
+ SUBFORMAT(MSBITS_20),
+ SUBFORMAT(MSBITS_24),
};
static const char * const snd_pcm_tstamp_mode_names[] = {
@@ -332,7 +328,7 @@ static const char *snd_pcm_oss_format_name(int format)
static void snd_pcm_proc_info_read(struct snd_pcm_substream *substream,
struct snd_info_buffer *buffer)
{
- struct snd_pcm_info *info;
+ struct snd_pcm_info *info __free(kfree) = NULL;
int err;
if (! substream)
@@ -345,7 +341,6 @@ static void snd_pcm_proc_info_read(struct snd_pcm_substream *substream,
err = snd_pcm_info(substream, info);
if (err < 0) {
snd_iprintf(buffer, "error %d\n", err);
- kfree(info);
return;
}
snd_iprintf(buffer, "card: %d\n", info->card);
@@ -359,7 +354,6 @@ static void snd_pcm_proc_info_read(struct snd_pcm_substream *substream,
snd_iprintf(buffer, "subclass: %d\n", info->dev_subclass);
snd_iprintf(buffer, "subdevices_count: %d\n", info->subdevices_count);
snd_iprintf(buffer, "subdevices_avail: %d\n", info->subdevices_avail);
- kfree(info);
}
static void snd_pcm_stream_proc_info_read(struct snd_info_entry *entry,
@@ -381,15 +375,15 @@ static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry,
struct snd_pcm_substream *substream = entry->private_data;
struct snd_pcm_runtime *runtime;
- mutex_lock(&substream->pcm->open_mutex);
+ guard(mutex)(&substream->pcm->open_mutex);
runtime = substream->runtime;
if (!runtime) {
snd_iprintf(buffer, "closed\n");
- goto unlock;
+ return;
}
if (runtime->state == SNDRV_PCM_STATE_OPEN) {
snd_iprintf(buffer, "no setup\n");
- goto unlock;
+ return;
}
snd_iprintf(buffer, "access: %s\n", snd_pcm_access_name(runtime->access));
snd_iprintf(buffer, "format: %s\n", snd_pcm_format_name(runtime->format));
@@ -408,8 +402,6 @@ static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry,
snd_iprintf(buffer, "OSS period frames: %lu\n", (unsigned long)runtime->oss.period_frames);
}
#endif
- unlock:
- mutex_unlock(&substream->pcm->open_mutex);
}
static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry,
@@ -418,15 +410,15 @@ static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry,
struct snd_pcm_substream *substream = entry->private_data;
struct snd_pcm_runtime *runtime;
- mutex_lock(&substream->pcm->open_mutex);
+ guard(mutex)(&substream->pcm->open_mutex);
runtime = substream->runtime;
if (!runtime) {
snd_iprintf(buffer, "closed\n");
- goto unlock;
+ return;
}
if (runtime->state == SNDRV_PCM_STATE_OPEN) {
snd_iprintf(buffer, "no setup\n");
- goto unlock;
+ return;
}
snd_iprintf(buffer, "tstamp_mode: %s\n", snd_pcm_tstamp_mode_name(runtime->tstamp_mode));
snd_iprintf(buffer, "period_step: %u\n", runtime->period_step);
@@ -436,8 +428,6 @@ static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry,
snd_iprintf(buffer, "silence_threshold: %lu\n", runtime->silence_threshold);
snd_iprintf(buffer, "silence_size: %lu\n", runtime->silence_size);
snd_iprintf(buffer, "boundary: %lu\n", runtime->boundary);
- unlock:
- mutex_unlock(&substream->pcm->open_mutex);
}
static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
@@ -448,17 +438,17 @@ static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
struct snd_pcm_status64 status;
int err;
- mutex_lock(&substream->pcm->open_mutex);
+ guard(mutex)(&substream->pcm->open_mutex);
runtime = substream->runtime;
if (!runtime) {
snd_iprintf(buffer, "closed\n");
- goto unlock;
+ return;
}
memset(&status, 0, sizeof(status));
err = snd_pcm_status64(substream, &status);
if (err < 0) {
snd_iprintf(buffer, "error %d\n", err);
- goto unlock;
+ return;
}
snd_iprintf(buffer, "state: %s\n", snd_pcm_state_name(status.state));
snd_iprintf(buffer, "owner_pid : %d\n", pid_vnr(substream->pid));
@@ -472,8 +462,9 @@ static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
snd_iprintf(buffer, "-----\n");
snd_iprintf(buffer, "hw_ptr : %ld\n", runtime->status->hw_ptr);
snd_iprintf(buffer, "appl_ptr : %ld\n", runtime->control->appl_ptr);
- unlock:
- mutex_unlock(&substream->pcm->open_mutex);
+#ifdef CONFIG_SND_PCM_XRUN_DEBUG
+ snd_iprintf(buffer, "xrun_counter: %d\n", substream->xrun_counter);
+#endif
}
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
@@ -601,19 +592,17 @@ static const struct attribute_group *pcm_dev_attr_groups[];
* PM callbacks: we need to deal only with suspend here, as the resume is
* triggered either from user-space or the driver's resume callback
*/
-#ifdef CONFIG_PM_SLEEP
static int do_pcm_suspend(struct device *dev)
{
- struct snd_pcm_str *pstr = container_of(dev, struct snd_pcm_str, dev);
+ struct snd_pcm_str *pstr = dev_get_drvdata(dev);
if (!pstr->pcm->no_device_suspend)
snd_pcm_suspend_all(pstr->pcm);
return 0;
}
-#endif
static const struct dev_pm_ops pcm_dev_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(do_pcm_suspend, NULL)
+ SYSTEM_SLEEP_PM_OPS(do_pcm_suspend, NULL)
};
/* device type for PCM -- basically only for passing PM callbacks */
@@ -650,11 +639,14 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
if (!substream_count)
return 0;
- snd_device_initialize(&pstr->dev, pcm->card);
- pstr->dev.groups = pcm_dev_attr_groups;
- pstr->dev.type = &pcm_dev_type;
- dev_set_name(&pstr->dev, "pcmC%iD%i%c", pcm->card->number, pcm->device,
+ err = snd_device_alloc(&pstr->dev, pcm->card);
+ if (err < 0)
+ return err;
+ dev_set_name(pstr->dev, "pcmC%iD%i%c", pcm->card->number, pcm->device,
stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c');
+ pstr->dev->groups = pcm_dev_attr_groups;
+ pstr->dev->type = &pcm_dev_type;
+ dev_set_drvdata(pstr->dev, pstr);
if (!pcm->internal) {
err = snd_pcm_stream_proc_init(pstr);
@@ -814,9 +806,7 @@ static void free_chmap(struct snd_pcm_str *pstr)
if (pstr->chmap_kctl) {
struct snd_card *card = pstr->pcm->card;
- down_write(&card->controls_rwsem);
snd_ctl_remove(card, pstr->chmap_kctl);
- up_write(&card->controls_rwsem);
pstr->chmap_kctl = NULL;
}
}
@@ -847,7 +837,7 @@ static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
#endif
free_chmap(pstr);
if (pstr->substream_count)
- put_device(&pstr->dev);
+ put_device(pstr->dev);
}
#if IS_ENABLED(CONFIG_SND_PCM_OSS)
@@ -981,6 +971,9 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
substream->pid = get_pid(task_pid(current));
pstr->substream_opened++;
*rsubstream = substream;
+#ifdef CONFIG_SND_PCM_XRUN_DEBUG
+ substream->xrun_counter = 0;
+#endif /* CONFIG_SND_PCM_XRUN_DEBUG */
return 0;
}
@@ -1000,9 +993,8 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
kfree(runtime->hw_constraints.rules);
/* Avoid concurrent access to runtime via PCM timer interface */
if (substream->timer) {
- spin_lock_irq(&substream->timer->lock);
- substream->runtime = NULL;
- spin_unlock_irq(&substream->timer->lock);
+ scoped_guard(spinlock_irq, &substream->timer->lock)
+ substream->runtime = NULL;
} else {
substream->runtime = NULL;
}
@@ -1017,7 +1009,7 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
static ssize_t pcm_class_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct snd_pcm_str *pstr = container_of(dev, struct snd_pcm_str, dev);
+ struct snd_pcm_str *pstr = dev_get_drvdata(dev);
struct snd_pcm *pcm = pstr->pcm;
const char *str;
static const char *strs[SNDRV_PCM_CLASS_LAST + 1] = {
@@ -1059,10 +1051,10 @@ static int snd_pcm_dev_register(struct snd_device *device)
return -ENXIO;
pcm = device->device_data;
- mutex_lock(&register_mutex);
+ guard(mutex)(&register_mutex);
err = snd_pcm_add(pcm);
if (err)
- goto unlock;
+ return err;
for (cidx = 0; cidx < 2; cidx++) {
int devtype = -1;
if (pcm->streams[cidx].substream == NULL)
@@ -1078,10 +1070,10 @@ static int snd_pcm_dev_register(struct snd_device *device)
/* register pcm */
err = snd_register_device(devtype, pcm->card, pcm->device,
&snd_pcm_f_ops[cidx], pcm,
- &pcm->streams[cidx].dev);
+ pcm->streams[cidx].dev);
if (err < 0) {
list_del_init(&pcm->list);
- goto unlock;
+ return err;
}
for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
@@ -1089,9 +1081,6 @@ static int snd_pcm_dev_register(struct snd_device *device)
}
pcm_call_notify(pcm, n_register);
-
- unlock:
- mutex_unlock(&register_mutex);
return err;
}
@@ -1101,8 +1090,8 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
struct snd_pcm_substream *substream;
int cidx;
- mutex_lock(&register_mutex);
- mutex_lock(&pcm->open_mutex);
+ guard(mutex)(&register_mutex);
+ guard(mutex)(&pcm->open_mutex);
wake_up(&pcm->open_wait);
list_del_init(&pcm->list);
@@ -1125,11 +1114,10 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
pcm_call_notify(pcm, n_disconnect);
for (cidx = 0; cidx < 2; cidx++) {
- snd_unregister_device(&pcm->streams[cidx].dev);
+ if (pcm->streams[cidx].dev)
+ snd_unregister_device(pcm->streams[cidx].dev);
free_chmap(&pcm->streams[cidx]);
}
- mutex_unlock(&pcm->open_mutex);
- mutex_unlock(&register_mutex);
return 0;
}
@@ -1154,7 +1142,7 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree)
!notify->n_unregister ||
!notify->n_disconnect))
return -EINVAL;
- mutex_lock(&register_mutex);
+ guard(mutex)(&register_mutex);
if (nfree) {
list_del(&notify->list);
list_for_each_entry(pcm, &snd_pcm_devices, list)
@@ -1164,7 +1152,6 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree)
list_for_each_entry(pcm, &snd_pcm_devices, list)
notify->n_register(pcm);
}
- mutex_unlock(&register_mutex);
return 0;
}
EXPORT_SYMBOL(snd_pcm_notify);
@@ -1180,7 +1167,7 @@ static void snd_pcm_proc_read(struct snd_info_entry *entry,
{
struct snd_pcm *pcm;
- mutex_lock(&register_mutex);
+ guard(mutex)(&register_mutex);
list_for_each_entry(pcm, &snd_pcm_devices, list) {
snd_iprintf(buffer, "%02i-%02i: %s : %s",
pcm->card->number, pcm->device, pcm->id, pcm->name);
@@ -1192,7 +1179,6 @@ static void snd_pcm_proc_read(struct snd_info_entry *entry,
pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count);
snd_iprintf(buffer, "\n");
}
- mutex_unlock(&register_mutex);
}
static struct snd_info_entry *snd_pcm_proc_entry;