summaryrefslogtreecommitdiff
path: root/sound/core/pcm_native.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core/pcm_native.c')
-rw-r--r--sound/core/pcm_native.c141
1 files changed, 53 insertions, 88 deletions
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index fb3dde4..6244911 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -19,7 +19,6 @@
*
*/
-#include <sound/driver.h>
#include <linux/mm.h>
#include <linux/file.h>
#include <linux/slab.h>
@@ -413,7 +412,6 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
runtime->period_size = params_period_size(params);
runtime->periods = params_periods(params);
runtime->buffer_size = params_buffer_size(params);
- runtime->tick_time = params_tick_time(params);
runtime->info = params->info;
runtime->rate_num = params->rate_num;
runtime->rate_den = params->rate_den;
@@ -433,9 +431,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
/* Default sw params */
runtime->tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
runtime->period_step = 1;
- runtime->sleep_min = 0;
runtime->control->avail_min = runtime->period_size;
- runtime->xfer_align = runtime->period_size;
runtime->start_threshold = 1;
runtime->stop_threshold = runtime->buffer_size;
runtime->silence_threshold = 0;
@@ -532,9 +528,6 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
return -EINVAL;
if (params->avail_min == 0)
return -EINVAL;
- if (params->xfer_align == 0 ||
- params->xfer_align % runtime->min_align != 0)
- return -EINVAL;
if (params->silence_size >= runtime->boundary) {
if (params->silence_threshold != 0)
return -EINVAL;
@@ -546,20 +539,14 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
}
snd_pcm_stream_lock_irq(substream);
runtime->tstamp_mode = params->tstamp_mode;
- runtime->sleep_min = params->sleep_min;
runtime->period_step = params->period_step;
runtime->control->avail_min = params->avail_min;
runtime->start_threshold = params->start_threshold;
runtime->stop_threshold = params->stop_threshold;
runtime->silence_threshold = params->silence_threshold;
runtime->silence_size = params->silence_size;
- runtime->xfer_align = params->xfer_align;
params->boundary = runtime->boundary;
if (snd_pcm_running(substream)) {
- if (runtime->sleep_min)
- snd_pcm_tick_prepare(substream);
- else
- snd_pcm_tick_set(substream, 0);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
runtime->silence_size > 0)
snd_pcm_playback_silence(substream, ULONG_MAX);
@@ -595,12 +582,13 @@ int snd_pcm_status(struct snd_pcm_substream *substream,
status->trigger_tstamp = runtime->trigger_tstamp;
if (snd_pcm_running(substream)) {
snd_pcm_update_hw_ptr(substream);
- if (runtime->tstamp_mode & SNDRV_PCM_TSTAMP_MMAP)
+ if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
status->tstamp = runtime->status->tstamp;
- else
- getnstimeofday(&status->tstamp);
- } else
- getnstimeofday(&status->tstamp);
+ goto _tstamp_end;
+ }
+ }
+ snd_pcm_gettime(runtime, &status->tstamp);
+ _tstamp_end:
status->appl_ptr = runtime->control->appl_ptr;
status->hw_ptr = runtime->status->hw_ptr;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
@@ -688,7 +676,7 @@ static void snd_pcm_trigger_tstamp(struct snd_pcm_substream *substream)
if (runtime->trigger_master == NULL)
return;
if (runtime->trigger_master == substream) {
- getnstimeofday(&runtime->trigger_tstamp);
+ snd_pcm_gettime(runtime, &runtime->trigger_tstamp);
} else {
snd_pcm_trigger_tstamp(runtime->trigger_master);
runtime->trigger_tstamp = runtime->trigger_master->runtime->trigger_tstamp;
@@ -875,8 +863,6 @@ static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state)
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
runtime->silence_size > 0)
snd_pcm_playback_silence(substream, ULONG_MAX);
- if (runtime->sleep_min)
- snd_pcm_tick_prepare(substream);
if (substream->timer)
snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MSTART,
&runtime->trigger_tstamp);
@@ -930,7 +916,6 @@ static void snd_pcm_post_stop(struct snd_pcm_substream *substream, int state)
snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MSTOP,
&runtime->trigger_tstamp);
runtime->status->state = state;
- snd_pcm_tick_set(substream, 0);
}
wake_up(&runtime->sleep);
}
@@ -1014,12 +999,9 @@ static void snd_pcm_post_pause(struct snd_pcm_substream *substream, int push)
snd_timer_notify(substream->timer,
SNDRV_TIMER_EVENT_MPAUSE,
&runtime->trigger_tstamp);
- snd_pcm_tick_set(substream, 0);
wake_up(&runtime->sleep);
} else {
runtime->status->state = SNDRV_PCM_STATE_RUNNING;
- if (runtime->sleep_min)
- snd_pcm_tick_prepare(substream);
if (substream->timer)
snd_timer_notify(substream->timer,
SNDRV_TIMER_EVENT_MCONTINUE,
@@ -1074,7 +1056,6 @@ static void snd_pcm_post_suspend(struct snd_pcm_substream *substream, int state)
&runtime->trigger_tstamp);
runtime->status->suspended_state = runtime->status->state;
runtime->status->state = SNDRV_PCM_STATE_SUSPENDED;
- snd_pcm_tick_set(substream, 0);
wake_up(&runtime->sleep);
}
@@ -1177,8 +1158,6 @@ static void snd_pcm_post_resume(struct snd_pcm_substream *substream, int state)
snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MRESUME,
&runtime->trigger_tstamp);
runtime->status->state = runtime->status->suspended_state;
- if (runtime->sleep_min)
- snd_pcm_tick_prepare(substream);
}
static struct action_ops snd_pcm_action_resume = {
@@ -1395,10 +1374,10 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state)
} else {
/* stop running stream */
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) {
- int state = snd_pcm_capture_avail(runtime) > 0 ?
+ int new_state = snd_pcm_capture_avail(runtime) > 0 ?
SNDRV_PCM_STATE_DRAINING : SNDRV_PCM_STATE_SETUP;
- snd_pcm_do_stop(substream, state);
- snd_pcm_post_stop(substream, state);
+ snd_pcm_do_stop(substream, new_state);
+ snd_pcm_post_stop(substream, new_state);
}
}
return 0;
@@ -2007,8 +1986,6 @@ int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream)
}
/* FIXME: this belong to lowlevel */
- snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_TICK_TIME,
- 1000000 / HZ, 1000000 / HZ);
snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
return 0;
@@ -2244,15 +2221,10 @@ static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *subst
}
if (frames > (snd_pcm_uframes_t)hw_avail)
frames = hw_avail;
- else
- frames -= frames % runtime->xfer_align;
appl_ptr = runtime->control->appl_ptr - frames;
if (appl_ptr < 0)
appl_ptr += runtime->boundary;
runtime->control->appl_ptr = appl_ptr;
- if (runtime->status->state == SNDRV_PCM_STATE_RUNNING &&
- runtime->sleep_min)
- snd_pcm_tick_prepare(substream);
ret = frames;
__end:
snd_pcm_stream_unlock_irq(substream);
@@ -2294,15 +2266,10 @@ static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substr
}
if (frames > (snd_pcm_uframes_t)hw_avail)
frames = hw_avail;
- else
- frames -= frames % runtime->xfer_align;
appl_ptr = runtime->control->appl_ptr - frames;
if (appl_ptr < 0)
appl_ptr += runtime->boundary;
runtime->control->appl_ptr = appl_ptr;
- if (runtime->status->state == SNDRV_PCM_STATE_RUNNING &&
- runtime->sleep_min)
- snd_pcm_tick_prepare(substream);
ret = frames;
__end:
snd_pcm_stream_unlock_irq(substream);
@@ -2345,15 +2312,10 @@ static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *subs
}
if (frames > (snd_pcm_uframes_t)avail)
frames = avail;
- else
- frames -= frames % runtime->xfer_align;
appl_ptr = runtime->control->appl_ptr + frames;
if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary)
appl_ptr -= runtime->boundary;
runtime->control->appl_ptr = appl_ptr;
- if (runtime->status->state == SNDRV_PCM_STATE_RUNNING &&
- runtime->sleep_min)
- snd_pcm_tick_prepare(substream);
ret = frames;
__end:
snd_pcm_stream_unlock_irq(substream);
@@ -2396,15 +2358,10 @@ static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *subst
}
if (frames > (snd_pcm_uframes_t)avail)
frames = avail;
- else
- frames -= frames % runtime->xfer_align;
appl_ptr = runtime->control->appl_ptr + frames;
if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary)
appl_ptr -= runtime->boundary;
runtime->control->appl_ptr = appl_ptr;
- if (runtime->status->state == SNDRV_PCM_STATE_RUNNING &&
- runtime->sleep_min)
- snd_pcm_tick_prepare(substream);
ret = frames;
__end:
snd_pcm_stream_unlock_irq(substream);
@@ -2519,6 +2476,21 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
return -EFAULT;
return 0;
}
+
+static int snd_pcm_tstamp(struct snd_pcm_substream *substream, int __user *_arg)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int arg;
+
+ if (get_user(arg, _arg))
+ return -EFAULT;
+ if (arg < 0 || arg > SNDRV_PCM_TSTAMP_TYPE_LAST)
+ return -EINVAL;
+ runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY;
+ if (arg == SNDRV_PCM_TSTAMP_TYPE_MONOTONIC)
+ runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC;
+ return 0;
+}
static int snd_pcm_common_ioctl1(struct file *file,
struct snd_pcm_substream *substream,
@@ -2531,8 +2503,10 @@ static int snd_pcm_common_ioctl1(struct file *file,
return put_user(SNDRV_PCM_VERSION, (int __user *)arg) ? -EFAULT : 0;
case SNDRV_PCM_IOCTL_INFO:
return snd_pcm_info_user(substream, arg);
- case SNDRV_PCM_IOCTL_TSTAMP: /* just for compatibility */
+ case SNDRV_PCM_IOCTL_TSTAMP: /* just for compatibility */
return 0;
+ case SNDRV_PCM_IOCTL_TTSTAMP:
+ return snd_pcm_tstamp(substream, arg);
case SNDRV_PCM_IOCTL_HW_REFINE:
return snd_pcm_hw_refine_user(substream, arg);
case SNDRV_PCM_IOCTL_HW_PARAMS:
@@ -3018,26 +2992,23 @@ static unsigned int snd_pcm_capture_poll(struct file *file, poll_table * wait)
/*
* mmap status record
*/
-static struct page * snd_pcm_mmap_status_nopage(struct vm_area_struct *area,
- unsigned long address, int *type)
+static int snd_pcm_mmap_status_fault(struct vm_area_struct *area,
+ struct vm_fault *vmf)
{
struct snd_pcm_substream *substream = area->vm_private_data;
struct snd_pcm_runtime *runtime;
- struct page * page;
if (substream == NULL)
- return NOPAGE_SIGBUS;
+ return VM_FAULT_SIGBUS;
runtime = substream->runtime;
- page = virt_to_page(runtime->status);
- get_page(page);
- if (type)
- *type = VM_FAULT_MINOR;
- return page;
+ vmf->page = virt_to_page(runtime->status);
+ get_page(vmf->page);
+ return 0;
}
static struct vm_operations_struct snd_pcm_vm_ops_status =
{
- .nopage = snd_pcm_mmap_status_nopage,
+ .fault = snd_pcm_mmap_status_fault,
};
static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
@@ -3061,26 +3032,23 @@ static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file
/*
* mmap control record
*/
-static struct page * snd_pcm_mmap_control_nopage(struct vm_area_struct *area,
- unsigned long address, int *type)
+static int snd_pcm_mmap_control_fault(struct vm_area_struct *area,
+ struct vm_fault *vmf)
{
struct snd_pcm_substream *substream = area->vm_private_data;
struct snd_pcm_runtime *runtime;
- struct page * page;
if (substream == NULL)
- return NOPAGE_SIGBUS;
+ return VM_FAULT_SIGBUS;
runtime = substream->runtime;
- page = virt_to_page(runtime->control);
- get_page(page);
- if (type)
- *type = VM_FAULT_MINOR;
- return page;
+ vmf->page = virt_to_page(runtime->control);
+ get_page(vmf->page);
+ return 0;
}
static struct vm_operations_struct snd_pcm_vm_ops_control =
{
- .nopage = snd_pcm_mmap_control_nopage,
+ .fault = snd_pcm_mmap_control_fault,
};
static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file,
@@ -3117,10 +3085,10 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file
#endif /* coherent mmap */
/*
- * nopage callback for mmapping a RAM page
+ * fault callback for mmapping a RAM page
*/
-static struct page *snd_pcm_mmap_data_nopage(struct vm_area_struct *area,
- unsigned long address, int *type)
+static int snd_pcm_mmap_data_fault(struct vm_area_struct *area,
+ struct vm_fault *vmf)
{
struct snd_pcm_substream *substream = area->vm_private_data;
struct snd_pcm_runtime *runtime;
@@ -3130,33 +3098,30 @@ static struct page *snd_pcm_mmap_data_nopage(struct vm_area_struct *area,
size_t dma_bytes;
if (substream == NULL)
- return NOPAGE_SIGBUS;
+ return VM_FAULT_SIGBUS;
runtime = substream->runtime;
- offset = area->vm_pgoff << PAGE_SHIFT;
- offset += address - area->vm_start;
- snd_assert((offset % PAGE_SIZE) == 0, return NOPAGE_SIGBUS);
+ offset = vmf->pgoff << PAGE_SHIFT;
dma_bytes = PAGE_ALIGN(runtime->dma_bytes);
if (offset > dma_bytes - PAGE_SIZE)
- return NOPAGE_SIGBUS;
+ return VM_FAULT_SIGBUS;
if (substream->ops->page) {
page = substream->ops->page(substream, offset);
- if (! page)
- return NOPAGE_OOM; /* XXX: is this really due to OOM? */
+ if (!page)
+ return VM_FAULT_SIGBUS;
} else {
vaddr = runtime->dma_area + offset;
page = virt_to_page(vaddr);
}
get_page(page);
- if (type)
- *type = VM_FAULT_MINOR;
- return page;
+ vmf->page = page;
+ return 0;
}
static struct vm_operations_struct snd_pcm_vm_ops_data =
{
.open = snd_pcm_mmap_data_open,
.close = snd_pcm_mmap_data_close,
- .nopage = snd_pcm_mmap_data_nopage,
+ .fault = snd_pcm_mmap_data_fault,
};
/*