aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2020-12-15 13:43:47 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2020-12-15 13:43:47 -0800
commitc367caf1a38b6f0a1aababafd88b00fefa625f9e (patch)
treef622681eff5785d5d15e6b04ca24b15cd7c473f9 /sound/core
parentMerge tag 'net-next-5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next (diff)
parentMerge tag 'asoc-v5.11' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus (diff)
downloadlinux-dev-c367caf1a38b6f0a1aababafd88b00fefa625f9e.tar.xz
linux-dev-c367caf1a38b6f0a1aababafd88b00fefa625f9e.zip
Merge tag 'sound-5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai: "Lots of changes (slightly more code increase than usual) at this time, while most of code changes are ASoC driver-specific. Here are some highlights: Core: - The new auxiliary bus implementation for Intel DSP, which will be used by other drivers as well - Lots of ASoC core cleanups and refactoring - UBSAN and KCSAN fixes in rawmidi, sequencer and a few others - Compress-offload API enhancement for the pause during draining HD- and USB-audio: - Enhancements of the USB-audio implicit feedback support, including better full-duplex operations - Continued CA0132 improvements and fixes - A few new quirk entries, HDMI audio fixes ASoC: - Support for boot time selection of Intel DSP firmware, which should help distros/users testing new stuff more easily; the kconfig was moved to boot time option, too - Some basic DPCM support in audio graph card - Removal of old pre-DT Freescale drivers - Support for Allwinner H6 I2S, Analog Devices ADAU1372, Intel Alderlake-S, GMediatek MT8192, NXP i.MX HDMI and XCVR, Realtek RT715, Qualcomm SM8250 and simple GPIO based muxes" * tag 'sound-5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (445 commits) ALSA: pcm: oss: Fix potential out-of-bounds shift ALSA: usb-audio: Fix potential out-of-bounds shift ALSA: hda/ca0132 - Add ZxR surround DAC setup. ALSA: hda/ca0132 - Add 8051 PLL write helper functions. ALSA: hda/hdmi: packet buffer index must be set before reading value ASoC: SOF: imx: update kernel-doc description ASoC: mediatek: mt8183: delete some unreachable code ASoC: mediatek: mt8183: add PM ops to machine drivers ASoC: topology: Fix wrong size check ASoC: topology: Add missing size check ASoC: SOF: Intel: hda: fix the condition passed to sof_dev_dbg_or_err ASoC: SOF: modify the SOF_DBG flags ASoC: SOF: Intel: hda: remove duplicated status dump ASoC: rt1015p: delay 300ms after SDB pulling high for calibration ASoC: rt1015p: move SDB control from trigger to DAPM ASoC: wm_adsp: remove "ctl" from list on error in wm_adsp_create_control() ALSA: usb-audio: Fix control 'access overflow' errors from chmap ALSA: hda/hdmi: always print pin NIDs as hexadecimal ALSA: hda/realtek - Add supported for more Lenovo ALC285 Headset Button ALSA: hda/ca0132 - Remove now unnecessary DSP setup functions. ...
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/compress_offload.c39
-rw-r--r--sound/core/oss/pcm_oss.c6
-rw-r--r--sound/core/rawmidi.c49
-rw-r--r--sound/core/seq/seq_clientmgr.c1
-rw-r--r--sound/core/seq/seq_queue.c27
-rw-r--r--sound/core/seq/seq_queue.h11
6 files changed, 75 insertions, 58 deletions
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index c1fec932c49d..debc30fcf5b3 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -709,11 +709,22 @@ static int snd_compr_pause(struct snd_compr_stream *stream)
{
int retval;
- if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
+ switch (stream->runtime->state) {
+ case SNDRV_PCM_STATE_RUNNING:
+ retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH);
+ if (!retval)
+ stream->runtime->state = SNDRV_PCM_STATE_PAUSED;
+ break;
+ case SNDRV_PCM_STATE_DRAINING:
+ if (!stream->device->use_pause_in_draining)
+ return -EPERM;
+ retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH);
+ if (!retval)
+ stream->pause_in_draining = true;
+ break;
+ default:
return -EPERM;
- retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH);
- if (!retval)
- stream->runtime->state = SNDRV_PCM_STATE_PAUSED;
+ }
return retval;
}
@@ -721,11 +732,22 @@ static int snd_compr_resume(struct snd_compr_stream *stream)
{
int retval;
- if (stream->runtime->state != SNDRV_PCM_STATE_PAUSED)
+ switch (stream->runtime->state) {
+ case SNDRV_PCM_STATE_PAUSED:
+ retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
+ if (!retval)
+ stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
+ break;
+ case SNDRV_PCM_STATE_DRAINING:
+ if (!stream->pause_in_draining)
+ return -EPERM;
+ retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
+ if (!retval)
+ stream->pause_in_draining = false;
+ break;
+ default:
return -EPERM;
- retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
- if (!retval)
- stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
+ }
return retval;
}
@@ -768,6 +790,7 @@ static int snd_compr_stop(struct snd_compr_stream *stream)
/* clear flags and stop any drain wait */
stream->partial_drain = false;
stream->metadata_set = false;
+ stream->pause_in_draining = false;
snd_compr_drain_notify(stream);
stream->runtime->total_bytes_available = 0;
stream->runtime->total_bytes_transferred = 0;
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 327ec42a36b0..de1917484647 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -1935,11 +1935,15 @@ static int snd_pcm_oss_set_subdivide(struct snd_pcm_oss_file *pcm_oss_file, int
static int snd_pcm_oss_set_fragment1(struct snd_pcm_substream *substream, unsigned int val)
{
struct snd_pcm_runtime *runtime;
+ int fragshift;
runtime = substream->runtime;
if (runtime->oss.subdivision || runtime->oss.fragshift)
return -EINVAL;
- runtime->oss.fragshift = val & 0xffff;
+ fragshift = val & 0xffff;
+ if (fragshift >= 31)
+ return -EINVAL;
+ runtime->oss.fragshift = fragshift;
runtime->oss.maxfrags = (val >> 16) & 0xffff;
if (runtime->oss.fragshift < 4) /* < 16 */
runtime->oss.fragshift = 4;
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index c78720a3299c..257ad5206240 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -95,11 +95,21 @@ static inline unsigned short snd_rawmidi_file_flags(struct file *file)
}
}
-static inline int snd_rawmidi_ready(struct snd_rawmidi_substream *substream)
+static inline bool __snd_rawmidi_ready(struct snd_rawmidi_runtime *runtime)
+{
+ return runtime->avail >= runtime->avail_min;
+}
+
+static bool snd_rawmidi_ready(struct snd_rawmidi_substream *substream)
{
struct snd_rawmidi_runtime *runtime = substream->runtime;
+ unsigned long flags;
+ bool ready;
- return runtime->avail >= runtime->avail_min;
+ spin_lock_irqsave(&runtime->lock, flags);
+ ready = __snd_rawmidi_ready(runtime);
+ spin_unlock_irqrestore(&runtime->lock, flags);
+ return ready;
}
static inline int snd_rawmidi_ready_append(struct snd_rawmidi_substream *substream,
@@ -1019,7 +1029,7 @@ int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,
if (result > 0) {
if (runtime->event)
schedule_work(&runtime->event_work);
- else if (snd_rawmidi_ready(substream))
+ else if (__snd_rawmidi_ready(runtime))
wake_up(&runtime->sleep);
}
spin_unlock_irqrestore(&runtime->lock, flags);
@@ -1098,7 +1108,7 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun
result = 0;
while (count > 0) {
spin_lock_irq(&runtime->lock);
- while (!snd_rawmidi_ready(substream)) {
+ while (!__snd_rawmidi_ready(runtime)) {
wait_queue_entry_t wait;
if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
@@ -1115,9 +1125,11 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun
return -ENODEV;
if (signal_pending(current))
return result > 0 ? result : -ERESTARTSYS;
- if (!runtime->avail)
- return result > 0 ? result : -EIO;
spin_lock_irq(&runtime->lock);
+ if (!runtime->avail) {
+ spin_unlock_irq(&runtime->lock);
+ return result > 0 ? result : -EIO;
+ }
}
spin_unlock_irq(&runtime->lock);
count1 = snd_rawmidi_kernel_read1(substream,
@@ -1255,7 +1267,7 @@ int __snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int coun
runtime->avail += count;
substream->bytes += count;
if (count > 0) {
- if (runtime->drain || snd_rawmidi_ready(substream))
+ if (runtime->drain || __snd_rawmidi_ready(runtime))
wake_up(&runtime->sleep);
}
return count;
@@ -1444,9 +1456,11 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf,
return -ENODEV;
if (signal_pending(current))
return result > 0 ? result : -ERESTARTSYS;
- if (!runtime->avail && !timeout)
- return result > 0 ? result : -EIO;
spin_lock_irq(&runtime->lock);
+ if (!runtime->avail && !timeout) {
+ spin_unlock_irq(&runtime->lock);
+ return result > 0 ? result : -EIO;
+ }
}
spin_unlock_irq(&runtime->lock);
count1 = snd_rawmidi_kernel_write1(substream, buf, NULL, count);
@@ -1526,6 +1540,7 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry,
struct snd_rawmidi *rmidi;
struct snd_rawmidi_substream *substream;
struct snd_rawmidi_runtime *runtime;
+ unsigned long buffer_size, avail, xruns;
rmidi = entry->private_data;
snd_iprintf(buffer, "%s\n\n", rmidi->name);
@@ -1544,13 +1559,16 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry,
" Owner PID : %d\n",
pid_vnr(substream->pid));
runtime = substream->runtime;
+ spin_lock_irq(&runtime->lock);
+ buffer_size = runtime->buffer_size;
+ avail = runtime->avail;
+ spin_unlock_irq(&runtime->lock);
snd_iprintf(buffer,
" Mode : %s\n"
" Buffer size : %lu\n"
" Avail : %lu\n",
runtime->oss ? "OSS compatible" : "native",
- (unsigned long) runtime->buffer_size,
- (unsigned long) runtime->avail);
+ buffer_size, avail);
}
}
}
@@ -1568,13 +1586,16 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry,
" Owner PID : %d\n",
pid_vnr(substream->pid));
runtime = substream->runtime;
+ spin_lock_irq(&runtime->lock);
+ buffer_size = runtime->buffer_size;
+ avail = runtime->avail;
+ xruns = runtime->xruns;
+ spin_unlock_irq(&runtime->lock);
snd_iprintf(buffer,
" Buffer size : %lu\n"
" Avail : %lu\n"
" Overruns : %lu\n",
- (unsigned long) runtime->buffer_size,
- (unsigned long) runtime->avail,
- (unsigned long) runtime->xruns);
+ buffer_size, avail, xruns);
}
}
}
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index cc93157fa950..f9f2fea58b32 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -279,7 +279,6 @@ static int seq_free_client1(struct snd_seq_client *client)
snd_seq_delete_all_ports(client);
snd_seq_queue_client_leave(client->number);
snd_use_lock_sync(&client->use_lock);
- snd_seq_queue_client_termination(client->number);
if (client->pool)
snd_seq_pool_delete(&client->pool);
spin_lock_irq(&clients_lock);
diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
index 71a6ea62c3be..13cfc2d47fa7 100644
--- a/sound/core/seq/seq_queue.c
+++ b/sound/core/seq/seq_queue.c
@@ -537,33 +537,6 @@ int snd_seq_queue_is_used(int queueid, int client)
/*----------------------------------------------------------------*/
-/* notification that client has left the system -
- * stop the timer on all queues owned by this client
- */
-void snd_seq_queue_client_termination(int client)
-{
- unsigned long flags;
- int i;
- struct snd_seq_queue *q;
- bool matched;
-
- for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
- if ((q = queueptr(i)) == NULL)
- continue;
- spin_lock_irqsave(&q->owner_lock, flags);
- matched = (q->owner == client);
- if (matched)
- q->klocked = 1;
- spin_unlock_irqrestore(&q->owner_lock, flags);
- if (matched) {
- if (q->timer->running)
- snd_seq_timer_stop(q->timer);
- snd_seq_timer_reset(q->timer);
- }
- queuefree(q);
- }
-}
-
/* final stage notification -
* remove cells for no longer exist client (for non-owned queue)
* or delete this queue (for owned queue)
diff --git a/sound/core/seq/seq_queue.h b/sound/core/seq/seq_queue.h
index 9254c8dbe5e3..c69105dc1a10 100644
--- a/sound/core/seq/seq_queue.h
+++ b/sound/core/seq/seq_queue.h
@@ -26,10 +26,10 @@ struct snd_seq_queue {
struct snd_seq_timer *timer; /* time keeper for this queue */
int owner; /* client that 'owns' the timer */
- unsigned int locked:1, /* timer is only accesibble by owner if set */
- klocked:1, /* kernel lock (after START) */
- check_again:1,
- check_blocked:1;
+ bool locked; /* timer is only accesibble by owner if set */
+ bool klocked; /* kernel lock (after START) */
+ bool check_again; /* concurrent access happened during check */
+ bool check_blocked; /* queue being checked */
unsigned int flags; /* status flags */
unsigned int info_flags; /* info for sync */
@@ -59,9 +59,6 @@ struct snd_seq_queue *snd_seq_queue_alloc(int client, int locked, unsigned int f
/* delete queue (destructor) */
int snd_seq_queue_delete(int client, int queueid);
-/* notification that client has left the system */
-void snd_seq_queue_client_termination(int client);
-
/* final stage */
void snd_seq_queue_client_leave(int client);