summaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/jack.c5
-rw-r--r--sound/core/pcm_lib.c41
-rw-r--r--sound/core/pcm_native.c12
-rw-r--r--sound/core/sound_oss.c6
4 files changed, 46 insertions, 18 deletions
diff --git a/sound/core/jack.c b/sound/core/jack.c
index 471e1e3..a06b165 100644
--- a/sound/core/jack.c
+++ b/sound/core/jack.c
@@ -155,7 +155,7 @@ EXPORT_SYMBOL(snd_jack_new);
* @jack: The jack to configure
* @parent: The device to set as parent for the jack.
*
- * Set the parent for the jack input device in the device tree. This
+ * Set the parent for the jack devices in the device tree. This
* function is only valid prior to registration of the jack. If no
* parent is configured then the parent device will be the sound card.
*/
@@ -179,6 +179,9 @@ EXPORT_SYMBOL(snd_jack_set_parent);
* mapping is provided but keys are enabled in the jack type then
* BTN_n numeric buttons will be reported.
*
+ * If jacks are not reporting via the input API this call will have no
+ * effect.
+ *
* Note that this is intended to be use by simple devices with small
* numbers of keys that can be reported. It is also possible to
* access the input device directly - devices with complex input
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 4d18941..8f312fa 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -313,9 +313,22 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base;
snd_pcm_sframes_t hdelta, delta;
unsigned long jdelta;
+ unsigned long curr_jiffies;
+ struct timespec curr_tstamp;
old_hw_ptr = runtime->status->hw_ptr;
+
+ /*
+ * group pointer, time and jiffies reads to allow for more
+ * accurate correlations/corrections.
+ * The values are stored at the end of this routine after
+ * corrections for hw_ptr position
+ */
pos = substream->ops->pointer(substream);
+ curr_jiffies = jiffies;
+ if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
+ snd_pcm_gettime(runtime, (struct timespec *)&curr_tstamp);
+
if (pos == SNDRV_PCM_POS_XRUN) {
xrun(substream);
return -EPIPE;
@@ -343,7 +356,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
delta = runtime->hw_ptr_interrupt + runtime->period_size;
if (delta > new_hw_ptr) {
/* check for double acknowledged interrupts */
- hdelta = jiffies - runtime->hw_ptr_jiffies;
+ hdelta = curr_jiffies - runtime->hw_ptr_jiffies;
if (hdelta > runtime->hw_ptr_buffer_jiffies/2) {
hw_base += runtime->buffer_size;
if (hw_base >= runtime->boundary)
@@ -388,7 +401,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
* Without regular period interrupts, we have to check
* the elapsed time to detect xruns.
*/
- jdelta = jiffies - runtime->hw_ptr_jiffies;
+ jdelta = curr_jiffies - runtime->hw_ptr_jiffies;
if (jdelta < runtime->hw_ptr_buffer_jiffies / 2)
goto no_delta_check;
hdelta = jdelta - delta * HZ / runtime->rate;
@@ -430,7 +443,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
if (hdelta < runtime->delay)
goto no_jiffies_check;
hdelta -= runtime->delay;
- jdelta = jiffies - runtime->hw_ptr_jiffies;
+ jdelta = curr_jiffies - runtime->hw_ptr_jiffies;
if (((hdelta * HZ) / runtime->rate) > jdelta + HZ/100) {
delta = jdelta /
(((runtime->period_size * HZ) / runtime->rate)
@@ -492,9 +505,9 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
}
runtime->hw_ptr_base = hw_base;
runtime->status->hw_ptr = new_hw_ptr;
- runtime->hw_ptr_jiffies = jiffies;
+ runtime->hw_ptr_jiffies = curr_jiffies;
if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
- snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp);
+ runtime->status->tstamp = curr_tstamp;
return snd_pcm_update_state(substream, runtime);
}
@@ -1894,6 +1907,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t xfer = 0;
snd_pcm_uframes_t offset = 0;
+ snd_pcm_uframes_t avail;
int err = 0;
if (size == 0)
@@ -1917,13 +1931,12 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(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);
+ avail = snd_pcm_playback_avail(runtime);
while (size > 0) {
snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
- snd_pcm_uframes_t avail;
snd_pcm_uframes_t cont;
- if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
- snd_pcm_update_hw_ptr(substream);
- avail = snd_pcm_playback_avail(runtime);
if (!avail) {
if (nonblock) {
err = -EAGAIN;
@@ -1971,6 +1984,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
offset += frames;
size -= frames;
xfer += frames;
+ avail -= frames;
if (runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
snd_pcm_playback_hw_avail(runtime) >= (snd_pcm_sframes_t)runtime->start_threshold) {
err = snd_pcm_start(substream);
@@ -2111,6 +2125,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t xfer = 0;
snd_pcm_uframes_t offset = 0;
+ snd_pcm_uframes_t avail;
int err = 0;
if (size == 0)
@@ -2141,13 +2156,12 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(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);
+ avail = snd_pcm_capture_avail(runtime);
while (size > 0) {
snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
- snd_pcm_uframes_t avail;
snd_pcm_uframes_t cont;
- if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
- snd_pcm_update_hw_ptr(substream);
- avail = snd_pcm_capture_avail(runtime);
if (!avail) {
if (runtime->status->state ==
SNDRV_PCM_STATE_DRAINING) {
@@ -2202,6 +2216,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
offset += frames;
size -= frames;
xfer += frames;
+ avail -= frames;
}
_end_unlock:
runtime->twake = 0;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 3fe99e6..53b5ada 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1360,7 +1360,14 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream,
static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state)
{
- substream->runtime->trigger_master = substream;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ switch (runtime->status->state) {
+ case SNDRV_PCM_STATE_OPEN:
+ case SNDRV_PCM_STATE_DISCONNECTED:
+ case SNDRV_PCM_STATE_SUSPENDED:
+ return -EBADFD;
+ }
+ runtime->trigger_master = substream;
return 0;
}
@@ -1379,6 +1386,9 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state)
case SNDRV_PCM_STATE_RUNNING:
runtime->status->state = SNDRV_PCM_STATE_DRAINING;
break;
+ case SNDRV_PCM_STATE_XRUN:
+ runtime->status->state = SNDRV_PCM_STATE_SETUP;
+ break;
default:
break;
}
diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c
index c700920..e952833 100644
--- a/sound/core/sound_oss.c
+++ b/sound/core/sound_oss.c
@@ -35,7 +35,7 @@
#include <linux/sound.h>
#include <linux/mutex.h>
-#define SNDRV_OSS_MINORS 128
+#define SNDRV_OSS_MINORS 256
static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS];
static DEFINE_MUTEX(sound_oss_mutex);
@@ -111,7 +111,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
int register1 = -1, register2 = -1;
struct device *carddev = snd_card_get_device_link(card);
- if (card && card->number >= 8)
+ if (card && card->number >= SNDRV_MINOR_OSS_DEVICES)
return 0; /* ignore silently */
if (minor < 0)
return minor;
@@ -170,7 +170,7 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev)
int track2 = -1;
struct snd_minor *mptr;
- if (card && card->number >= 8)
+ if (card && card->number >= SNDRV_MINOR_OSS_DEVICES)
return 0;
if (minor < 0)
return minor;
OpenPOWER on IntegriCloud