|
@@ -87,7 +87,7 @@ MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-128) for dummy driver.");
|
|
|
module_param(fake_buffer, bool, 0444);
|
|
|
MODULE_PARM_DESC(fake_buffer, "Fake buffer allocations.");
|
|
|
#ifdef CONFIG_HIGH_RES_TIMERS
|
|
|
-module_param(hrtimer, bool, 0444);
|
|
|
+module_param(hrtimer, bool, 0644);
|
|
|
MODULE_PARM_DESC(hrtimer, "Use hrtimer as the timer source.");
|
|
|
#endif
|
|
|
|
|
@@ -109,6 +109,9 @@ struct dummy_timer_ops {
|
|
|
snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *);
|
|
|
};
|
|
|
|
|
|
+#define get_dummy_ops(substream) \
|
|
|
+ (*(const struct dummy_timer_ops **)(substream)->runtime->private_data)
|
|
|
+
|
|
|
struct dummy_model {
|
|
|
const char *name;
|
|
|
int (*playback_constraints)(struct snd_pcm_runtime *runtime);
|
|
@@ -137,7 +140,6 @@ struct snd_dummy {
|
|
|
int iobox;
|
|
|
struct snd_kcontrol *cd_volume_ctl;
|
|
|
struct snd_kcontrol *cd_switch_ctl;
|
|
|
- const struct dummy_timer_ops *timer_ops;
|
|
|
};
|
|
|
|
|
|
/*
|
|
@@ -231,6 +233,8 @@ static struct dummy_model *dummy_models[] = {
|
|
|
*/
|
|
|
|
|
|
struct dummy_systimer_pcm {
|
|
|
+ /* ops must be the first item */
|
|
|
+ const struct dummy_timer_ops *timer_ops;
|
|
|
spinlock_t lock;
|
|
|
struct timer_list timer;
|
|
|
unsigned long base_time;
|
|
@@ -366,6 +370,8 @@ static const struct dummy_timer_ops dummy_systimer_ops = {
|
|
|
*/
|
|
|
|
|
|
struct dummy_hrtimer_pcm {
|
|
|
+ /* ops must be the first item */
|
|
|
+ const struct dummy_timer_ops *timer_ops;
|
|
|
ktime_t base_time;
|
|
|
ktime_t period_time;
|
|
|
atomic_t running;
|
|
@@ -492,31 +498,25 @@ static const struct dummy_timer_ops dummy_hrtimer_ops = {
|
|
|
|
|
|
static int dummy_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
|
|
|
{
|
|
|
- struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
|
|
|
-
|
|
|
switch (cmd) {
|
|
|
case SNDRV_PCM_TRIGGER_START:
|
|
|
case SNDRV_PCM_TRIGGER_RESUME:
|
|
|
- return dummy->timer_ops->start(substream);
|
|
|
+ return get_dummy_ops(substream)->start(substream);
|
|
|
case SNDRV_PCM_TRIGGER_STOP:
|
|
|
case SNDRV_PCM_TRIGGER_SUSPEND:
|
|
|
- return dummy->timer_ops->stop(substream);
|
|
|
+ return get_dummy_ops(substream)->stop(substream);
|
|
|
}
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
static int dummy_pcm_prepare(struct snd_pcm_substream *substream)
|
|
|
{
|
|
|
- struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
|
|
|
-
|
|
|
- return dummy->timer_ops->prepare(substream);
|
|
|
+ return get_dummy_ops(substream)->prepare(substream);
|
|
|
}
|
|
|
|
|
|
static snd_pcm_uframes_t dummy_pcm_pointer(struct snd_pcm_substream *substream)
|
|
|
{
|
|
|
- struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
|
|
|
-
|
|
|
- return dummy->timer_ops->pointer(substream);
|
|
|
+ return get_dummy_ops(substream)->pointer(substream);
|
|
|
}
|
|
|
|
|
|
static struct snd_pcm_hardware dummy_pcm_hardware = {
|
|
@@ -562,17 +562,19 @@ static int dummy_pcm_open(struct snd_pcm_substream *substream)
|
|
|
struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
|
|
|
struct dummy_model *model = dummy->model;
|
|
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
|
|
+ const struct dummy_timer_ops *ops;
|
|
|
int err;
|
|
|
|
|
|
- dummy->timer_ops = &dummy_systimer_ops;
|
|
|
+ ops = &dummy_systimer_ops;
|
|
|
#ifdef CONFIG_HIGH_RES_TIMERS
|
|
|
if (hrtimer)
|
|
|
- dummy->timer_ops = &dummy_hrtimer_ops;
|
|
|
+ ops = &dummy_hrtimer_ops;
|
|
|
#endif
|
|
|
|
|
|
- err = dummy->timer_ops->create(substream);
|
|
|
+ err = ops->create(substream);
|
|
|
if (err < 0)
|
|
|
return err;
|
|
|
+ get_dummy_ops(substream) = ops;
|
|
|
|
|
|
runtime->hw = dummy->pcm_hw;
|
|
|
if (substream->pcm->device & 1) {
|
|
@@ -594,7 +596,7 @@ static int dummy_pcm_open(struct snd_pcm_substream *substream)
|
|
|
err = model->capture_constraints(substream->runtime);
|
|
|
}
|
|
|
if (err < 0) {
|
|
|
- dummy->timer_ops->free(substream);
|
|
|
+ get_dummy_ops(substream)->free(substream);
|
|
|
return err;
|
|
|
}
|
|
|
return 0;
|
|
@@ -602,8 +604,7 @@ static int dummy_pcm_open(struct snd_pcm_substream *substream)
|
|
|
|
|
|
static int dummy_pcm_close(struct snd_pcm_substream *substream)
|
|
|
{
|
|
|
- struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
|
|
|
- dummy->timer_ops->free(substream);
|
|
|
+ get_dummy_ops(substream)->free(substream);
|
|
|
return 0;
|
|
|
}
|
|
|
|