2
* PCM timer handling on ctxfi
4
* This source file is released under GPL v2 license (no other versions).
5
* See the COPYING file included in the main directory of this source
6
* distribution for the license terms and conditions.
9
#include <linux/slab.h>
10
#include <linux/math64.h>
11
#include <linux/moduleparam.h>
12
#include <sound/core.h>
13
#include <sound/pcm.h>
15
#include "cthardware.h"
18
static bool use_system_timer;
19
MODULE_PARM_DESC(use_system_timer, "Force to use system-timer");
20
module_param(use_system_timer, bool, 0444);
23
void (*init)(struct ct_timer_instance *);
24
void (*prepare)(struct ct_timer_instance *);
25
void (*start)(struct ct_timer_instance *);
26
void (*stop)(struct ct_timer_instance *);
27
void (*free_instance)(struct ct_timer_instance *);
28
void (*interrupt)(struct ct_timer *);
29
void (*free_global)(struct ct_timer *);
32
/* timer instance -- assigned to each PCM stream */
33
struct ct_timer_instance {
35
struct ct_timer *timer_base;
36
struct ct_atc_pcm *apcm;
37
struct snd_pcm_substream *substream;
38
struct timer_list timer;
39
struct list_head instance_list;
40
struct list_head running_list;
41
unsigned int position;
42
unsigned int frag_count;
43
unsigned int running:1;
44
unsigned int need_update:1;
47
/* timer instance manager */
49
spinlock_t lock; /* global timer lock (for xfitimer) */
50
spinlock_t list_lock; /* lock for instance list */
52
const struct ct_timer_ops *ops;
53
struct list_head instance_head;
54
struct list_head running_head;
55
unsigned int wc; /* current wallclock */
56
unsigned int irq_handling:1; /* in IRQ handling */
57
unsigned int reprogram:1; /* need to reprogram the internval */
58
unsigned int running:1; /* global timer running */
63
* system-timer-based updates
66
static void ct_systimer_callback(struct timer_list *t)
68
struct ct_timer_instance *ti = from_timer(ti, t, timer);
69
struct snd_pcm_substream *substream = ti->substream;
70
struct snd_pcm_runtime *runtime = substream->runtime;
71
struct ct_atc_pcm *apcm = ti->apcm;
72
unsigned int period_size = runtime->period_size;
73
unsigned int buffer_size = runtime->buffer_size;
75
unsigned int position, dist, interval;
77
position = substream->ops->pointer(substream);
78
dist = (position + buffer_size - ti->position) % buffer_size;
79
if (dist >= period_size ||
80
position / period_size != ti->position / period_size) {
81
apcm->interrupt(apcm);
82
ti->position = position;
84
/* Add extra HZ*5/1000 to avoid overrun issue when recording
85
* at 8kHz in 8-bit format or at 88kHz in 24-bit format. */
86
interval = ((period_size - (position % period_size))
87
* HZ + (runtime->rate - 1)) / runtime->rate + HZ * 5 / 1000;
88
spin_lock_irqsave(&ti->lock, flags);
90
mod_timer(&ti->timer, jiffies + interval);
91
spin_unlock_irqrestore(&ti->lock, flags);
94
static void ct_systimer_init(struct ct_timer_instance *ti)
96
timer_setup(&ti->timer, ct_systimer_callback, 0);
99
static void ct_systimer_start(struct ct_timer_instance *ti)
101
struct snd_pcm_runtime *runtime = ti->substream->runtime;
104
spin_lock_irqsave(&ti->lock, flags);
106
mod_timer(&ti->timer,
107
jiffies + (runtime->period_size * HZ +
108
(runtime->rate - 1)) / runtime->rate);
109
spin_unlock_irqrestore(&ti->lock, flags);
112
static void ct_systimer_stop(struct ct_timer_instance *ti)
116
spin_lock_irqsave(&ti->lock, flags);
118
del_timer(&ti->timer);
119
spin_unlock_irqrestore(&ti->lock, flags);
122
static void ct_systimer_prepare(struct ct_timer_instance *ti)
124
ct_systimer_stop(ti);
125
try_to_del_timer_sync(&ti->timer);
128
#define ct_systimer_free ct_systimer_prepare
130
static const struct ct_timer_ops ct_systimer_ops = {
131
.init = ct_systimer_init,
132
.free_instance = ct_systimer_free,
133
.prepare = ct_systimer_prepare,
134
.start = ct_systimer_start,
135
.stop = ct_systimer_stop,
140
* Handling multiple streams using a global emu20k1 timer irq
143
#define CT_TIMER_FREQ 48000
145
#define MAX_TICKS ((1 << 13) - 1)
147
static void ct_xfitimer_irq_rearm(struct ct_timer *atimer, int ticks)
149
struct hw *hw = atimer->atc->hw;
150
if (ticks > MAX_TICKS)
152
hw->set_timer_tick(hw, ticks);
153
if (!atimer->running)
154
hw->set_timer_irq(hw, 1);
158
static void ct_xfitimer_irq_stop(struct ct_timer *atimer)
160
if (atimer->running) {
161
struct hw *hw = atimer->atc->hw;
162
hw->set_timer_irq(hw, 0);
163
hw->set_timer_tick(hw, 0);
168
static inline unsigned int ct_xfitimer_get_wc(struct ct_timer *atimer)
170
struct hw *hw = atimer->atc->hw;
171
return hw->get_wc(hw);
175
* reprogram the timer interval;
176
* checks the running instance list and determines the next timer interval.
177
* also updates the each stream position, returns the number of streams
178
* to call snd_pcm_period_elapsed() appropriately
180
* call this inside the lock and irq disabled
182
static int ct_xfitimer_reprogram(struct ct_timer *atimer, int can_update)
184
struct ct_timer_instance *ti;
185
unsigned int min_intr = (unsigned int)-1;
187
unsigned int wc, diff;
189
if (list_empty(&atimer->running_head)) {
190
ct_xfitimer_irq_stop(atimer);
191
atimer->reprogram = 0; /* clear flag */
195
wc = ct_xfitimer_get_wc(atimer);
196
diff = wc - atimer->wc;
198
list_for_each_entry(ti, &atimer->running_head, running_list) {
199
if (ti->frag_count > diff)
200
ti->frag_count -= diff;
203
unsigned int period_size, rate;
205
period_size = ti->substream->runtime->period_size;
206
rate = ti->substream->runtime->rate;
207
pos = ti->substream->ops->pointer(ti->substream);
208
if (pos / period_size != ti->position / period_size) {
214
pos = period_size - pos;
215
ti->frag_count = div_u64((u64)pos * CT_TIMER_FREQ +
218
if (ti->need_update && !can_update)
219
min_intr = 0; /* pending to the next irq */
220
if (ti->frag_count < min_intr)
221
min_intr = ti->frag_count;
224
if (min_intr < MIN_TICKS)
225
min_intr = MIN_TICKS;
226
ct_xfitimer_irq_rearm(atimer, min_intr);
227
atimer->reprogram = 0; /* clear flag */
231
/* look through the instance list and call period_elapsed if needed */
232
static void ct_xfitimer_check_period(struct ct_timer *atimer)
234
struct ct_timer_instance *ti;
237
spin_lock_irqsave(&atimer->list_lock, flags);
238
list_for_each_entry(ti, &atimer->instance_head, instance_list) {
239
if (ti->running && ti->need_update) {
241
ti->apcm->interrupt(ti->apcm);
244
spin_unlock_irqrestore(&atimer->list_lock, flags);
247
/* Handle timer-interrupt */
248
static void ct_xfitimer_callback(struct ct_timer *atimer)
253
spin_lock_irqsave(&atimer->lock, flags);
254
atimer->irq_handling = 1;
256
update = ct_xfitimer_reprogram(atimer, 1);
257
spin_unlock(&atimer->lock);
259
ct_xfitimer_check_period(atimer);
260
spin_lock(&atimer->lock);
261
} while (atimer->reprogram);
262
atimer->irq_handling = 0;
263
spin_unlock_irqrestore(&atimer->lock, flags);
266
static void ct_xfitimer_prepare(struct ct_timer_instance *ti)
268
ti->frag_count = ti->substream->runtime->period_size;
274
/* start/stop the timer */
275
static void ct_xfitimer_update(struct ct_timer *atimer)
279
spin_lock_irqsave(&atimer->lock, flags);
280
if (atimer->irq_handling) {
281
/* reached from IRQ handler; let it handle later */
282
atimer->reprogram = 1;
283
spin_unlock_irqrestore(&atimer->lock, flags);
287
ct_xfitimer_irq_stop(atimer);
288
ct_xfitimer_reprogram(atimer, 0);
289
spin_unlock_irqrestore(&atimer->lock, flags);
292
static void ct_xfitimer_start(struct ct_timer_instance *ti)
294
struct ct_timer *atimer = ti->timer_base;
297
spin_lock_irqsave(&atimer->lock, flags);
298
if (list_empty(&ti->running_list))
299
atimer->wc = ct_xfitimer_get_wc(atimer);
302
list_add(&ti->running_list, &atimer->running_head);
303
spin_unlock_irqrestore(&atimer->lock, flags);
304
ct_xfitimer_update(atimer);
307
static void ct_xfitimer_stop(struct ct_timer_instance *ti)
309
struct ct_timer *atimer = ti->timer_base;
312
spin_lock_irqsave(&atimer->lock, flags);
313
list_del_init(&ti->running_list);
315
spin_unlock_irqrestore(&atimer->lock, flags);
316
ct_xfitimer_update(atimer);
319
static void ct_xfitimer_free_global(struct ct_timer *atimer)
321
ct_xfitimer_irq_stop(atimer);
324
static const struct ct_timer_ops ct_xfitimer_ops = {
325
.prepare = ct_xfitimer_prepare,
326
.start = ct_xfitimer_start,
327
.stop = ct_xfitimer_stop,
328
.interrupt = ct_xfitimer_callback,
329
.free_global = ct_xfitimer_free_global,
336
struct ct_timer_instance *
337
ct_timer_instance_new(struct ct_timer *atimer, struct ct_atc_pcm *apcm)
339
struct ct_timer_instance *ti;
341
ti = kzalloc(sizeof(*ti), GFP_KERNEL);
344
spin_lock_init(&ti->lock);
345
INIT_LIST_HEAD(&ti->instance_list);
346
INIT_LIST_HEAD(&ti->running_list);
347
ti->timer_base = atimer;
349
ti->substream = apcm->substream;
350
if (atimer->ops->init)
351
atimer->ops->init(ti);
353
spin_lock_irq(&atimer->list_lock);
354
list_add(&ti->instance_list, &atimer->instance_head);
355
spin_unlock_irq(&atimer->list_lock);
360
void ct_timer_prepare(struct ct_timer_instance *ti)
362
if (ti->timer_base->ops->prepare)
363
ti->timer_base->ops->prepare(ti);
368
void ct_timer_start(struct ct_timer_instance *ti)
370
struct ct_timer *atimer = ti->timer_base;
371
atimer->ops->start(ti);
374
void ct_timer_stop(struct ct_timer_instance *ti)
376
struct ct_timer *atimer = ti->timer_base;
377
atimer->ops->stop(ti);
380
void ct_timer_instance_free(struct ct_timer_instance *ti)
382
struct ct_timer *atimer = ti->timer_base;
384
atimer->ops->stop(ti); /* to be sure */
385
if (atimer->ops->free_instance)
386
atimer->ops->free_instance(ti);
388
spin_lock_irq(&atimer->list_lock);
389
list_del(&ti->instance_list);
390
spin_unlock_irq(&atimer->list_lock);
399
static void ct_timer_interrupt(void *data, unsigned int status)
401
struct ct_timer *timer = data;
403
/* Interval timer interrupt */
404
if ((status & IT_INT) && timer->ops->interrupt)
405
timer->ops->interrupt(timer);
408
struct ct_timer *ct_timer_new(struct ct_atc *atc)
410
struct ct_timer *atimer;
413
atimer = kzalloc(sizeof(*atimer), GFP_KERNEL);
416
spin_lock_init(&atimer->lock);
417
spin_lock_init(&atimer->list_lock);
418
INIT_LIST_HEAD(&atimer->instance_head);
419
INIT_LIST_HEAD(&atimer->running_head);
422
if (!use_system_timer && hw->set_timer_irq) {
423
dev_info(atc->card->dev, "Use xfi-native timer\n");
424
atimer->ops = &ct_xfitimer_ops;
425
hw->irq_callback_data = atimer;
426
hw->irq_callback = ct_timer_interrupt;
428
dev_info(atc->card->dev, "Use system timer\n");
429
atimer->ops = &ct_systimer_ops;
434
void ct_timer_free(struct ct_timer *atimer)
436
struct hw *hw = atimer->atc->hw;
437
hw->irq_callback = NULL;
438
if (atimer->ops->free_global)
439
atimer->ops->free_global(atimer);