summaryrefslogtreecommitdiff
path: root/sound/core
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-06-06 09:08:38 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2018-06-06 09:08:38 -0700
commit126f7051b4daa3716d9af2851dcb55316e4c2b25 (patch)
treee2f29bf57f28110d8fe42faaded6f83ffc52ec06 /sound/core
parent135c5504a600ff9b06e321694fbcac78a9530cd4 (diff)
parentd4d5a1cd298e67cb68cca8dc7dd1ea3942cce3ff (diff)
Merge tag 'sound-4.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai: "We've got many code additions at this cycle as a result of quite a few new drivers. Below are highlights: Core stuff: - Fix the long-standing issue with the device registration order; the control device is now registered at last - PCM locking code cleanups for RT kernels - Fixes for possible races in ALSA timer resolution accesses - TLV offset definitions in uapi ASoC: - Many fixes for the topology stuff, including fixes for v4 ABI compatibility - Lots of cleanups / quirks for Intel platforms based on Realtek CODECs - Continued componentization works, removing legacy CODEC stuff - Conversion of OMAP DMA to the new, more standard SDMA-PCM driver - Fixes and updates to Cirrus Logic SoC drivers - New Qualcomm DSP support - New drivers for Analog SSM2305, Atmel I2S controllers, Mediatek MT6351, MT6797 and MT7622, Qualcomm DSPs, Realtek RT1305, RT1306 and RT5668 and TI TSCS454 HD-audio: - Finally better support for some CA0132 boards, allowing Windows firmware - HP Spectre x360 support along with a bulk of COEF stuff - Blacklisting power save default some known boards reported on Fedora USB-audio: - Continued improvements on UAC3 support; now BADD is supported - Fixes / improvements for Dell WD15 dock - Allow DMA coherent pages for PCM buffers for ARCH, MIPS & co Others: - New Xen sound frontend driver support - Cache implementation and other improvements for FireWire DICE - Conversions to octal permissions in allover places" * tag 'sound-4.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (386 commits) ASoC: dapm: delete dapm_kcontrol_data paths list before freeing it ALSA: usb-audio: remove redundant check on err ASoC: topology: Move skl-tplg-interface.h to uapi ASoC: topology: Move v4 manifest header data structures to uapi ASoC: topology: Improve backwards compatibility with v4 topology files ALSA: pci/hda: Remove unused, broken, header file ASoC: TSCS454: Add Support ASoC: Intel: kbl: Move codec sysclk config to codec_init function ASoC: simple-card: set cpu dai clk in hw_params ALSA: hda - Handle kzalloc() failure in snd_hda_attach_pcm_stream() ALSA: oxygen: use match_string() helper ASoC: dapm: use match_string() helper ASoC: max98095: use match_string() helper ASoC: max98088: use match_string() helper ASoC: Intel: bytcr_rt5651: Set card long_name based on quirks ASoC: mt6797-mt6351: add hostless phone call path ASoC: mt6797: add Hostless DAI ASoC: mt6797: add PCM interface ASoC: mediatek: export mtk-afe symbols as needed ASoC: codecs: PCM1789: include gpio/consumer.h ...
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/compress_offload.c2
-rw-r--r--sound/core/device.c9
-rw-r--r--sound/core/info.c6
-rw-r--r--sound/core/init.c4
-rw-r--r--sound/core/oss/mixer_oss.c2
-rw-r--r--sound/core/oss/pcm_oss.c2
-rw-r--r--sound/core/pcm.c10
-rw-r--r--sound/core/pcm_compat.c10
-rw-r--r--sound/core/pcm_lib.c15
-rw-r--r--sound/core/pcm_local.h18
-rw-r--r--sound/core/pcm_memory.c2
-rw-r--r--sound/core/pcm_native.c261
-rw-r--r--sound/core/seq/seq_ports.c2
-rw-r--r--sound/core/seq/seq_timer.c4
-rw-r--r--sound/core/timer.c48
-rw-r--r--sound/core/vmaster.c16
16 files changed, 184 insertions, 227 deletions
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index 4563432badba..4b01a37c836e 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -1001,7 +1001,7 @@ static int snd_compress_proc_init(struct snd_compr *compr)
compr->card->proc_root);
if (!entry)
return -ENOMEM;
- entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
+ entry->mode = S_IFDIR | 0555;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
return -ENOMEM;
diff --git a/sound/core/device.c b/sound/core/device.c
index cb0e46f66cc9..535102d564e3 100644
--- a/sound/core/device.c
+++ b/sound/core/device.c
@@ -240,6 +240,15 @@ void snd_device_free_all(struct snd_card *card)
if (snd_BUG_ON(!card))
return;
+ list_for_each_entry_safe_reverse(dev, next, &card->devices, list) {
+ /* exception: free ctl and lowlevel stuff later */
+ if (dev->type == SNDRV_DEV_CONTROL ||
+ dev->type == SNDRV_DEV_LOWLEVEL)
+ continue;
+ __snd_device_free(dev);
+ }
+
+ /* free all */
list_for_each_entry_safe_reverse(dev, next, &card->devices, list)
__snd_device_free(dev);
}
diff --git a/sound/core/info.c b/sound/core/info.c
index 4b36767af9e1..fe502bc5e6d2 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -454,7 +454,7 @@ static struct snd_info_entry *create_subdir(struct module *mod,
entry = snd_info_create_module_entry(mod, name, NULL);
if (!entry)
return NULL;
- entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
+ entry->mode = S_IFDIR | 0555;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
return NULL;
@@ -470,7 +470,7 @@ int __init snd_info_init(void)
snd_proc_root = snd_info_create_entry("asound", NULL);
if (!snd_proc_root)
return -ENOMEM;
- snd_proc_root->mode = S_IFDIR | S_IRUGO | S_IXUGO;
+ snd_proc_root->mode = S_IFDIR | 0555;
snd_proc_root->p = proc_mkdir("asound", NULL);
if (!snd_proc_root->p)
goto error;
@@ -716,7 +716,7 @@ snd_info_create_entry(const char *name, struct snd_info_entry *parent)
kfree(entry);
return NULL;
}
- entry->mode = S_IFREG | S_IRUGO;
+ entry->mode = S_IFREG | 0444;
entry->content = SNDRV_INFO_CONTENT_TEXT;
mutex_init(&entry->access);
INIT_LIST_HEAD(&entry->children);
diff --git a/sound/core/init.c b/sound/core/init.c
index 79b4df1c1dc7..4849c611c0fe 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -703,7 +703,7 @@ card_id_store_attr(struct device *dev, struct device_attribute *attr,
return count;
}
-static DEVICE_ATTR(id, S_IRUGO | S_IWUSR, card_id_show_attr, card_id_store_attr);
+static DEVICE_ATTR(id, 0644, card_id_show_attr, card_id_store_attr);
static ssize_t
card_number_show_attr(struct device *dev,
@@ -713,7 +713,7 @@ card_number_show_attr(struct device *dev,
return scnprintf(buf, PAGE_SIZE, "%i\n", card->number);
}
-static DEVICE_ATTR(number, S_IRUGO, card_number_show_attr, NULL);
+static DEVICE_ATTR(number, 0444, card_number_show_attr, NULL);
static struct attribute *card_dev_attrs[] = {
&dev_attr_id.attr,
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 379bf486ccc7..64d904bee8bb 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -1247,7 +1247,7 @@ static void snd_mixer_oss_proc_init(struct snd_mixer_oss *mixer)
if (! entry)
return;
entry->content = SNDRV_INFO_CONTENT_TEXT;
- entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
+ entry->mode = S_IFREG | 0644;
entry->c.text.read = snd_mixer_oss_proc_read;
entry->c.text.write = snd_mixer_oss_proc_write;
entry->private_data = mixer;
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 1980f68246cb..905a53c1cde5 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -3045,7 +3045,7 @@ static void snd_pcm_oss_proc_init(struct snd_pcm *pcm)
continue;
if ((entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root)) != NULL) {
entry->content = SNDRV_INFO_CONTENT_TEXT;
- entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
+ entry->mode = S_IFREG | 0644;
entry->c.text.read = snd_pcm_oss_proc_read;
entry->c.text.write = snd_pcm_oss_proc_write;
entry->private_data = pstr;
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 66ac89aad681..c352bfb973cc 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -530,7 +530,7 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr)
pcm->card->proc_root);
if (!entry)
return -ENOMEM;
- entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
+ entry->mode = S_IFDIR | 0555;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
return -ENOMEM;
@@ -552,7 +552,7 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr)
if (entry) {
entry->c.text.read = snd_pcm_xrun_debug_read;
entry->c.text.write = snd_pcm_xrun_debug_write;
- entry->mode |= S_IWUSR;
+ entry->mode |= 0200;
entry->private_data = pstr;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
@@ -590,7 +590,7 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
substream->pstr->proc_root);
if (!entry)
return -ENOMEM;
- entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
+ entry->mode = S_IFDIR | 0555;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
return -ENOMEM;
@@ -647,7 +647,7 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
entry->private_data = substream;
entry->c.text.read = NULL;
entry->c.text.write = snd_pcm_xrun_injection_write;
- entry->mode = S_IFREG | S_IWUSR;
+ entry->mode = S_IFREG | 0200;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
entry = NULL;
@@ -1087,7 +1087,7 @@ static ssize_t show_pcm_class(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%s\n", str);
}
-static DEVICE_ATTR(pcm_class, S_IRUGO, show_pcm_class, NULL);
+static DEVICE_ATTR(pcm_class, 0444, show_pcm_class, NULL);
static struct attribute *pcm_dev_attrs[] = {
&dev_attr_pcm_class.attr,
NULL
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
index 6491afbb5fd5..39d853bfa5ac 100644
--- a/sound/core/pcm_compat.c
+++ b/sound/core/pcm_compat.c
@@ -45,10 +45,7 @@ static int snd_pcm_ioctl_rewind_compat(struct snd_pcm_substream *substream,
if (get_user(frames, src))
return -EFAULT;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- err = snd_pcm_playback_rewind(substream, frames);
- else
- err = snd_pcm_capture_rewind(substream, frames);
+ err = snd_pcm_rewind(substream, frames);
if (put_user(err, src))
return -EFAULT;
return err < 0 ? err : 0;
@@ -62,10 +59,7 @@ static int snd_pcm_ioctl_forward_compat(struct snd_pcm_substream *substream,
if (get_user(frames, src))
return -EFAULT;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- err = snd_pcm_playback_forward(substream, frames);
- else
- err = snd_pcm_capture_forward(substream, frames);
+ err = snd_pcm_forward(substream, frames);
if (put_user(err, src))
return -EFAULT;
return err < 0 ? err : 0;
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index f4a19509cccf..44b5ae833082 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -191,10 +191,7 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream,
{
snd_pcm_uframes_t avail;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- avail = snd_pcm_playback_avail(runtime);
- else
- avail = snd_pcm_capture_avail(runtime);
+ avail = snd_pcm_avail(substream);
if (avail > runtime->avail_max)
runtime->avail_max = avail;
if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
@@ -1856,10 +1853,7 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
* This check must happen after been added to the waitqueue
* and having current state be INTERRUPTIBLE.
*/
- if (is_playback)
- avail = snd_pcm_playback_avail(runtime);
- else
- avail = snd_pcm_capture_avail(runtime);
+ avail = snd_pcm_avail(substream);
if (avail >= runtime->twake)
break;
snd_pcm_stream_unlock_irq(substream);
@@ -2175,10 +2169,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
runtime->twake = runtime->control->avail_min ? : 1;
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
snd_pcm_update_hw_ptr(substream);
- if (is_playback)
- avail = snd_pcm_playback_avail(runtime);
- else
- avail = snd_pcm_capture_avail(runtime);
+ avail = snd_pcm_avail(substream);
while (size > 0) {
snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
snd_pcm_uframes_t cont;
diff --git a/sound/core/pcm_local.h b/sound/core/pcm_local.h
index 16f254732b2a..7a499d02df6c 100644
--- a/sound/core/pcm_local.h
+++ b/sound/core/pcm_local.h
@@ -36,6 +36,24 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream);
void snd_pcm_playback_silence(struct snd_pcm_substream *substream,
snd_pcm_uframes_t new_hw_ptr);
+static inline snd_pcm_uframes_t
+snd_pcm_avail(struct snd_pcm_substream *substream)
+{
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ return snd_pcm_playback_avail(substream->runtime);
+ else
+ return snd_pcm_capture_avail(substream->runtime);
+}
+
+static inline snd_pcm_uframes_t
+snd_pcm_hw_avail(struct snd_pcm_substream *substream)
+{
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ return snd_pcm_playback_hw_avail(substream->runtime);
+ else
+ return snd_pcm_capture_hw_avail(substream->runtime);
+}
+
#ifdef CONFIG_SND_PCM_TIMER
void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream);
void snd_pcm_timer_init(struct snd_pcm_substream *substream);
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index ae33e456708c..4b5356a10315 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -201,7 +201,7 @@ static inline void preallocate_info_init(struct snd_pcm_substream *substream)
if ((entry = snd_info_create_card_entry(substream->pcm->card, "prealloc", substream->proc_root)) != NULL) {
entry->c.text.read = snd_pcm_lib_preallocate_proc_read;
entry->c.text.write = snd_pcm_lib_preallocate_proc_write;
- entry->mode |= S_IWUSR;
+ entry->mode |= 0200;
entry->private_data = substream;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 0e875d5a9e86..04c6301394d0 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -99,6 +99,57 @@ static inline void down_write_nonblock(struct rw_semaphore *lock)
cond_resched();
}
+#define PCM_LOCK_DEFAULT 0
+#define PCM_LOCK_IRQ 1
+#define PCM_LOCK_IRQSAVE 2
+
+static unsigned long __snd_pcm_stream_lock_mode(struct snd_pcm_substream *substream,
+ unsigned int mode)
+{
+ unsigned long flags = 0;
+ if (substream->pcm->nonatomic) {
+ down_read_nested(&snd_pcm_link_rwsem, SINGLE_DEPTH_NESTING);
+ mutex_lock(&substream->self_group.mutex);
+ } else {
+ switch (mode) {
+ case PCM_LOCK_DEFAULT:
+ read_lock(&snd_pcm_link_rwlock);
+ break;
+ case PCM_LOCK_IRQ:
+ read_lock_irq(&snd_pcm_link_rwlock);
+ break;
+ case PCM_LOCK_IRQSAVE:
+ read_lock_irqsave(&snd_pcm_link_rwlock, flags);
+ break;
+ }
+ spin_lock(&substream->self_group.lock);
+ }
+ return flags;
+}
+
+static void __snd_pcm_stream_unlock_mode(struct snd_pcm_substream *substream,
+ unsigned int mode, unsigned long flags)
+{
+ if (substream->pcm->nonatomic) {
+ mutex_unlock(&substream->self_group.mutex);
+ up_read(&snd_pcm_link_rwsem);
+ } else {
+ spin_unlock(&substream->self_group.lock);
+
+ switch (mode) {
+ case PCM_LOCK_DEFAULT:
+ read_unlock(&snd_pcm_link_rwlock);
+ break;
+ case PCM_LOCK_IRQ:
+ read_unlock_irq(&snd_pcm_link_rwlock);
+ break;
+ case PCM_LOCK_IRQSAVE:
+ read_unlock_irqrestore(&snd_pcm_link_rwlock, flags);
+ break;
+ }
+ }
+}
+
/**
* snd_pcm_stream_lock - Lock the PCM stream
* @substream: PCM substream
@@ -109,13 +160,7 @@ static inline void down_write_nonblock(struct rw_semaphore *lock)
*/
void snd_pcm_stream_lock(struct snd_pcm_substream *substream)
{
- if (substream->pcm->nonatomic) {
- down_read_nested(&snd_pcm_link_rwsem, SINGLE_DEPTH_NESTING);
- mutex_lock(&substream->self_group.mutex);
- } else {
- read_lock(&snd_pcm_link_rwlock);
- spin_lock(&substream->self_group.lock);
- }
+ __snd_pcm_stream_lock_mode(substream, PCM_LOCK_DEFAULT);
}
EXPORT_SYMBOL_GPL(snd_pcm_stream_lock);
@@ -127,13 +172,7 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_lock);
*/
void snd_pcm_stream_unlock(struct snd_pcm_substream *substream)
{
- if (substream->pcm->nonatomic) {
- mutex_unlock(&substream->self_group.mutex);
- up_read(&snd_pcm_link_rwsem);
- } else {
- spin_unlock(&substream->self_group.lock);
- read_unlock(&snd_pcm_link_rwlock);
- }
+ __snd_pcm_stream_unlock_mode(substream, PCM_LOCK_DEFAULT, 0);
}
EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock);
@@ -147,9 +186,7 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock);
*/
void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream)
{
- if (!substream->pcm->nonatomic)
- local_irq_disable();
- snd_pcm_stream_lock(substream);
+ __snd_pcm_stream_lock_mode(substream, PCM_LOCK_IRQ);
}
EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq);
@@ -161,19 +198,13 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq);
*/
void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream)
{
- snd_pcm_stream_unlock(substream);
- if (!substream->pcm->nonatomic)
- local_irq_enable();
+ __snd_pcm_stream_unlock_mode(substream, PCM_LOCK_IRQ, 0);
}
EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irq);
unsigned long _snd_pcm_stream_lock_irqsave(struct snd_pcm_substream *substream)
{
- unsigned long flags = 0;
- if (!substream->pcm->nonatomic)
- local_irq_save(flags);
- snd_pcm_stream_lock(substream);
- return flags;
+ return __snd_pcm_stream_lock_mode(substream, PCM_LOCK_IRQSAVE);
}
EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave);
@@ -187,9 +218,7 @@ EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave);
void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream,
unsigned long flags)
{
- snd_pcm_stream_unlock(substream);
- if (!substream->pcm->nonatomic)
- local_irq_restore(flags);
+ __snd_pcm_stream_unlock_mode(substream, PCM_LOCK_IRQSAVE, flags);
}
EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore);
@@ -857,6 +886,18 @@ static int snd_pcm_sw_params_user(struct snd_pcm_substream *substream,
return err;
}
+static inline snd_pcm_uframes_t
+snd_pcm_calc_delay(struct snd_pcm_substream *substream)
+{
+ snd_pcm_uframes_t delay;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ delay = snd_pcm_playback_hw_avail(substream->runtime);
+ else
+ delay = snd_pcm_capture_avail(substream->runtime);
+ return delay + substream->runtime->delay;
+}
+
int snd_pcm_status(struct snd_pcm_substream *substream,
struct snd_pcm_status *status)
{
@@ -908,21 +949,9 @@ int snd_pcm_status(struct snd_pcm_substream *substream,
_tstamp_end:
status->appl_ptr = runtime->control->appl_ptr;
status->hw_ptr = runtime->status->hw_ptr;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- status->avail = snd_pcm_playback_avail(runtime);
- if (runtime->status->state == SNDRV_PCM_STATE_RUNNING ||
- runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
- status->delay = runtime->buffer_size - status->avail;
- status->delay += runtime->delay;
- } else
- status->delay = 0;
- } else {
- status->avail = snd_pcm_capture_avail(runtime);
- if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
- status->delay = status->avail + runtime->delay;
- else
- status->delay = 0;
- }
+ status->avail = snd_pcm_avail(substream);
+ status->delay = snd_pcm_running(substream) ?
+ snd_pcm_calc_delay(substream) : 0;
status->avail_max = runtime->avail_max;
status->overrange = runtime->overrange;
runtime->avail_max = 0;
@@ -2610,10 +2639,9 @@ static snd_pcm_sframes_t rewind_appl_ptr(struct snd_pcm_substream *substream,
return ret < 0 ? 0 : frames;
}
-static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream,
- snd_pcm_uframes_t frames)
+static snd_pcm_sframes_t snd_pcm_rewind(struct snd_pcm_substream *substream,
+ snd_pcm_uframes_t frames)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t ret;
if (frames == 0)
@@ -2623,33 +2651,14 @@ static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *subst
ret = do_pcm_hwsync(substream);
if (!ret)
ret = rewind_appl_ptr(substream, frames,
- snd_pcm_playback_hw_avail(runtime));
+ snd_pcm_hw_avail(substream));
snd_pcm_stream_unlock_irq(substream);
return ret;
}
-static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substream,
- snd_pcm_uframes_t frames)
+static snd_pcm_sframes_t snd_pcm_forward(struct snd_pcm_substream *substream,
+ snd_pcm_uframes_t frames)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_sframes_t ret;
-
- if (frames == 0)
- return 0;
-
- snd_pcm_stream_lock_irq(substream);
- ret = do_pcm_hwsync(substream);
- if (!ret)
- ret = rewind_appl_ptr(substream, frames,
- snd_pcm_capture_hw_avail(runtime));
- snd_pcm_stream_unlock_irq(substream);
- return ret;
-}
-
-static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *substream,
- snd_pcm_uframes_t frames)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t ret;
if (frames == 0)
@@ -2659,25 +2668,7 @@ static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *subs
ret = do_pcm_hwsync(substream);
if (!ret)
ret = forward_appl_ptr(substream, frames,
- snd_pcm_playback_avail(runtime));
- snd_pcm_stream_unlock_irq(substream);
- return ret;
-}
-
-static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *substream,
- snd_pcm_uframes_t frames)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_sframes_t ret;
-
- if (frames == 0)
- return 0;
-
- snd_pcm_stream_lock_irq(substream);
- ret = do_pcm_hwsync(substream);
- if (!ret)
- ret = forward_appl_ptr(substream, frames,
- snd_pcm_capture_avail(runtime));
+ snd_pcm_avail(substream));
snd_pcm_stream_unlock_irq(substream);
return ret;
}
@@ -2695,19 +2686,13 @@ static int snd_pcm_hwsync(struct snd_pcm_substream *substream)
static int snd_pcm_delay(struct snd_pcm_substream *substream,
snd_pcm_sframes_t *delay)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
int err;
snd_pcm_sframes_t n = 0;
snd_pcm_stream_lock_irq(substream);
err = do_pcm_hwsync(substream);
- if (!err) {
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- n = snd_pcm_playback_hw_avail(runtime);
- else
- n = snd_pcm_capture_avail(runtime);
- n += runtime->delay;
- }
+ if (!err)
+ n = snd_pcm_calc_delay(substream);
snd_pcm_stream_unlock_irq(substream);
if (!err)
*delay = n;
@@ -2834,10 +2819,7 @@ static int snd_pcm_rewind_ioctl(struct snd_pcm_substream *substream,
return -EFAULT;
if (put_user(0, _frames))
return -EFAULT;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- result = snd_pcm_playback_rewind(substream, frames);
- else
- result = snd_pcm_capture_rewind(substream, frames);
+ result = snd_pcm_rewind(substream, frames);
__put_user(result, _frames);
return result < 0 ? result : 0;
}
@@ -2852,10 +2834,7 @@ static int snd_pcm_forward_ioctl(struct snd_pcm_substream *substream,
return -EFAULT;
if (put_user(0, _frames))
return -EFAULT;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- result = snd_pcm_playback_forward(substream, frames);
- else
- result = snd_pcm_capture_forward(substream, frames);
+ result = snd_pcm_forward(substream, frames);
__put_user(result, _frames);
return result < 0 ? result : 0;
}
@@ -2998,7 +2977,7 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
/* provided only for OSS; capture-only and no value returned */
if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
return -EINVAL;
- result = snd_pcm_capture_forward(substream, *frames);
+ result = snd_pcm_forward(substream, *frames);
return result < 0 ? result : 0;
}
case SNDRV_PCM_IOCTL_HW_PARAMS:
@@ -3140,82 +3119,46 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from)
return result;
}
-static __poll_t snd_pcm_playback_poll(struct file *file, poll_table * wait)
+static __poll_t snd_pcm_poll(struct file *file, poll_table *wait)
{
struct snd_pcm_file *pcm_file;
struct snd_pcm_substream *substream;
struct snd_pcm_runtime *runtime;
- __poll_t mask;
+ __poll_t mask, ok;
snd_pcm_uframes_t avail;
pcm_file = file->private_data;
substream = pcm_file->substream;
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ ok = EPOLLOUT | EPOLLWRNORM;
+ else
+ ok = EPOLLIN | EPOLLRDNORM;
if (PCM_RUNTIME_CHECK(substream))
- return EPOLLOUT | EPOLLWRNORM | EPOLLERR;
- runtime = substream->runtime;
-
- poll_wait(file, &runtime->sleep, wait);
+ return ok | EPOLLERR;
- snd_pcm_stream_lock_irq(substream);
- avail = snd_pcm_playback_avail(runtime);
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_RUNNING:
- case SNDRV_PCM_STATE_PREPARED:
- case SNDRV_PCM_STATE_PAUSED:
- if (avail >= runtime->control->avail_min) {
- mask = EPOLLOUT | EPOLLWRNORM;
- break;
- }
- /* Fall through */
- case SNDRV_PCM_STATE_DRAINING:
- mask = 0;
- break;
- default:
- mask = EPOLLOUT | EPOLLWRNORM | EPOLLERR;
- break;
- }
- snd_pcm_stream_unlock_irq(substream);
- return mask;
-}
-
-static __poll_t snd_pcm_capture_poll(struct file *file, poll_table * wait)
-{
- struct snd_pcm_file *pcm_file;
- struct snd_pcm_substream *substream;
- struct snd_pcm_runtime *runtime;
- __poll_t mask;
- snd_pcm_uframes_t avail;
-
- pcm_file = file->private_data;
-
- substream = pcm_file->substream;
- if (PCM_RUNTIME_CHECK(substream))
- return EPOLLIN | EPOLLRDNORM | EPOLLERR;
runtime = substream->runtime;
-
poll_wait(file, &runtime->sleep, wait);
+ mask = 0;
snd_pcm_stream_lock_irq(substream);
- avail = snd_pcm_capture_avail(runtime);
+ avail = snd_pcm_avail(substream);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_PAUSED:
- if (avail >= runtime->control->avail_min) {
- mask = EPOLLIN | EPOLLRDNORM;
- break;
- }
- mask = 0;
+ if (avail >= runtime->control->avail_min)
+ mask = ok;
break;
case SNDRV_PCM_STATE_DRAINING:
- if (avail > 0) {
- mask = EPOLLIN | EPOLLRDNORM;
- break;
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ mask = ok;
+ if (!avail)
+ mask |= EPOLLERR;
}
- /* Fall through */
+ break;
default:
- mask = EPOLLIN | EPOLLRDNORM | EPOLLERR;
+ mask = ok | EPOLLERR;
break;
}
snd_pcm_stream_unlock_irq(substream);
@@ -3707,7 +3650,7 @@ const struct file_operations snd_pcm_f_ops[2] = {
.open = snd_pcm_playback_open,
.release = snd_pcm_release,
.llseek = no_llseek,
- .poll = snd_pcm_playback_poll,
+ .poll = snd_pcm_poll,
.unlocked_ioctl = snd_pcm_ioctl,
.compat_ioctl = snd_pcm_ioctl_compat,
.mmap = snd_pcm_mmap,
@@ -3721,7 +3664,7 @@ const struct file_operations snd_pcm_f_ops[2] = {
.open = snd_pcm_capture_open,
.release = snd_pcm_release,
.llseek = no_llseek,
- .poll = snd_pcm_capture_poll,
+ .poll = snd_pcm_poll,
.unlocked_ioctl = snd_pcm_ioctl,
.compat_ioctl = snd_pcm_ioctl_compat,
.mmap = snd_pcm_mmap,
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index d21ece9f8d73..24d90abfc64d 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -669,7 +669,7 @@ int snd_seq_event_port_attach(int client,
/* Set up the port */
memset(&portinfo, 0, sizeof(portinfo));
portinfo.addr.client = client;
- strlcpy(portinfo.name, portname ? portname : "Unamed port",
+ strlcpy(portinfo.name, portname ? portname : "Unnamed port",
sizeof(portinfo.name));
portinfo.capability = cap;
diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c
index 23167578231f..f587d0e27476 100644
--- a/sound/core/seq/seq_timer.c
+++ b/sound/core/seq/seq_timer.c
@@ -371,9 +371,7 @@ static int initialize_timer(struct snd_seq_timer *tmr)
tmr->ticks = 1;
if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE)) {
- unsigned long r = t->hw.resolution;
- if (! r && t->hw.c_resolution)
- r = t->hw.c_resolution(t);
+ unsigned long r = snd_timer_resolution(tmr->timeri);
if (r) {
tmr->ticks = (unsigned int)(1000000000uL / (r * freq));
if (! tmr->ticks)
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 0ddcae495838..665089c45560 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -427,25 +427,35 @@ int snd_timer_close(struct snd_timer_instance *timeri)
}
EXPORT_SYMBOL(snd_timer_close);
+static unsigned long snd_timer_hw_resolution(struct snd_timer *timer)
+{
+ if (timer->hw.c_resolution)
+ return timer->hw.c_resolution(timer);
+ else
+ return timer->hw.resolution;
+}
+
unsigned long snd_timer_resolution(struct snd_timer_instance *timeri)
{
struct snd_timer * timer;
+ unsigned long ret = 0;
+ unsigned long flags;
if (timeri == NULL)
return 0;
timer = timeri->timer;
if (timer) {
- if (timer->hw.c_resolution)
- return timer->hw.c_resolution(timer);
- return timer->hw.resolution;
+ spin_lock_irqsave(&timer->lock, flags);
+ ret = snd_timer_hw_resolution(timer);
+ spin_unlock_irqrestore(&timer->lock, flags);
}
- return 0;
+ return ret;
}
EXPORT_SYMBOL(snd_timer_resolution);
static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
{
- struct snd_timer *timer;
+ struct snd_timer *timer = ti->timer;
unsigned long resolution = 0;
struct snd_timer_instance *ts;
struct timespec tstamp;
@@ -457,14 +467,14 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_START ||
event > SNDRV_TIMER_EVENT_PAUSE))
return;
- if (event == SNDRV_TIMER_EVENT_START ||
- event == SNDRV_TIMER_EVENT_CONTINUE)
- resolution = snd_timer_resolution(ti);
+ if (timer &&
+ (event == SNDRV_TIMER_EVENT_START ||
+ event == SNDRV_TIMER_EVENT_CONTINUE))
+ resolution = snd_timer_hw_resolution(timer);
if (ti->ccallback)
ti->ccallback(ti, event, &tstamp, resolution);
if (ti->flags & SNDRV_TIMER_IFLG_SLAVE)
return;
- timer = ti->timer;
if (timer == NULL)
return;
if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)
@@ -771,10 +781,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
spin_lock_irqsave(&timer->lock, flags);
/* remember the current resolution */
- if (timer->hw.c_resolution)
- resolution = timer->hw.c_resolution(timer);
- else
- resolution = timer->hw.resolution;
+ resolution = snd_timer_hw_resolution(timer);
/* loop for all active instances
* Here we cannot use list_for_each_entry because the active_list of a
@@ -1014,12 +1021,8 @@ void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstam
spin_lock_irqsave(&timer->lock, flags);
if (event == SNDRV_TIMER_EVENT_MSTART ||
event == SNDRV_TIMER_EVENT_MCONTINUE ||
- event == SNDRV_TIMER_EVENT_MRESUME) {
- if (timer->hw.c_resolution)
- resolution = timer->hw.c_resolution(timer);
- else
- resolution = timer->hw.resolution;
- }
+ event == SNDRV_TIMER_EVENT_MRESUME)
+ resolution = snd_timer_hw_resolution(timer);
list_for_each_entry(ti, &timer->active_list_head, active_list) {
if (ti->ccallback)
ti->ccallback(ti, event, tstamp, resolution);
@@ -1656,10 +1659,8 @@ static int snd_timer_user_gstatus(struct file *file,
mutex_lock(&register_mutex);
t = snd_timer_find(&tid);
if (t != NULL) {
- if (t->hw.c_resolution)
- gstatus.resolution = t->hw.c_resolution(t);
- else
- gstatus.resolution = t->hw.resolution;
+ spin_lock_irq(&t->lock);
+ gstatus.resolution = snd_timer_hw_resolution(t);
if (t->hw.precise_resolution) {
t->hw.precise_resolution(t, &gstatus.resolution_num,
&gstatus.resolution_den);
@@ -1667,6 +1668,7 @@ static int snd_timer_user_gstatus(struct file *file,
gstatus.resolution_num = gstatus.resolution;
gstatus.resolution_den = 1000000000uL;
}
+ spin_unlock_irq(&t->lock);
} else {
err = -ENODEV;
}
diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c
index 9e96186742d0..58fa3f94722a 100644
--- a/sound/core/vmaster.c
+++ b/sound/core/vmaster.c
@@ -421,13 +421,15 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
kctl->private_free = master_free;
/* additional (constant) TLV read */
- if (tlv &&
- (tlv[0] == SNDRV_CTL_TLVT_DB_SCALE ||
- tlv[0] == SNDRV_CTL_TLVT_DB_MINMAX ||
- tlv[0] == SNDRV_CTL_TLVT_DB_MINMAX_MUTE)) {
- kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
- memcpy(master->tlv, tlv, sizeof(master->tlv));
- kctl->tlv.p = master->tlv;
+ if (tlv) {
+ unsigned int type = tlv[SNDRV_CTL_TLVO_TYPE];
+ if (type == SNDRV_CTL_TLVT_DB_SCALE ||
+ type == SNDRV_CTL_TLVT_DB_MINMAX ||
+ type == SNDRV_CTL_TLVT_DB_MINMAX_MUTE) {
+ kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
+ memcpy(master->tlv, tlv, sizeof(master->tlv));
+ kctl->tlv.p = master->tlv;
+ }
}
return kctl;