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 int use_system_timer
;
19 MODULE_PARM_DESC(use_system_timer
, "Foce to use system-timer");
20 module_param(use_system_timer
, bool, S_IRUGO
);
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 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(unsigned long data
)
68 struct ct_timer_instance
*ti
= (struct ct_timer_instance
*)data
;
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 setup_timer(&ti
->timer
, ct_systimer_callback
,
100 static void ct_systimer_start(struct ct_timer_instance
*ti
)
102 struct snd_pcm_runtime
*runtime
= ti
->substream
->runtime
;
105 spin_lock_irqsave(&ti
->lock
, flags
);
107 mod_timer(&ti
->timer
,
108 jiffies
+ (runtime
->period_size
* HZ
+
109 (runtime
->rate
- 1)) / runtime
->rate
);
110 spin_unlock_irqrestore(&ti
->lock
, flags
);
113 static void ct_systimer_stop(struct ct_timer_instance
*ti
)
117 spin_lock_irqsave(&ti
->lock
, flags
);
119 del_timer(&ti
->timer
);
120 spin_unlock_irqrestore(&ti
->lock
, flags
);
123 static void ct_systimer_prepare(struct ct_timer_instance
*ti
)
125 ct_systimer_stop(ti
);
126 try_to_del_timer_sync(&ti
->timer
);
129 #define ct_systimer_free ct_systimer_prepare
131 static struct ct_timer_ops ct_systimer_ops
= {
132 .init
= ct_systimer_init
,
133 .free_instance
= ct_systimer_free
,
134 .prepare
= ct_systimer_prepare
,
135 .start
= ct_systimer_start
,
136 .stop
= ct_systimer_stop
,
141 * Handling multiple streams using a global emu20k1 timer irq
144 #define CT_TIMER_FREQ 48000
146 #define MAX_TICKS ((1 << 13) - 1)
148 static void ct_xfitimer_irq_rearm(struct ct_timer
*atimer
, int ticks
)
150 struct hw
*hw
= atimer
->atc
->hw
;
151 if (ticks
> MAX_TICKS
)
153 hw
->set_timer_tick(hw
, ticks
);
154 if (!atimer
->running
)
155 hw
->set_timer_irq(hw
, 1);
159 static void ct_xfitimer_irq_stop(struct ct_timer
*atimer
)
161 if (atimer
->running
) {
162 struct hw
*hw
= atimer
->atc
->hw
;
163 hw
->set_timer_irq(hw
, 0);
164 hw
->set_timer_tick(hw
, 0);
169 static inline unsigned int ct_xfitimer_get_wc(struct ct_timer
*atimer
)
171 struct hw
*hw
= atimer
->atc
->hw
;
172 return hw
->get_wc(hw
);
176 * reprogram the timer interval;
177 * checks the running instance list and determines the next timer interval.
178 * also updates the each stream position, returns the number of streams
179 * to call snd_pcm_period_elapsed() appropriately
181 * call this inside the lock and irq disabled
183 static int ct_xfitimer_reprogram(struct ct_timer
*atimer
, int can_update
)
185 struct ct_timer_instance
*ti
;
186 unsigned int min_intr
= (unsigned int)-1;
188 unsigned int wc
, diff
;
190 if (list_empty(&atimer
->running_head
)) {
191 ct_xfitimer_irq_stop(atimer
);
192 atimer
->reprogram
= 0; /* clear flag */
196 wc
= ct_xfitimer_get_wc(atimer
);
197 diff
= wc
- atimer
->wc
;
199 list_for_each_entry(ti
, &atimer
->running_head
, running_list
) {
200 if (ti
->frag_count
> diff
)
201 ti
->frag_count
-= diff
;
204 unsigned int period_size
, rate
;
206 period_size
= ti
->substream
->runtime
->period_size
;
207 rate
= ti
->substream
->runtime
->rate
;
208 pos
= ti
->substream
->ops
->pointer(ti
->substream
);
209 if (pos
/ period_size
!= ti
->position
/ period_size
) {
215 pos
= period_size
- pos
;
216 ti
->frag_count
= div_u64((u64
)pos
* CT_TIMER_FREQ
+
219 if (ti
->need_update
&& !can_update
)
220 min_intr
= 0; /* pending to the next irq */
221 if (ti
->frag_count
< min_intr
)
222 min_intr
= ti
->frag_count
;
225 if (min_intr
< MIN_TICKS
)
226 min_intr
= MIN_TICKS
;
227 ct_xfitimer_irq_rearm(atimer
, min_intr
);
228 atimer
->reprogram
= 0; /* clear flag */
232 /* look through the instance list and call period_elapsed if needed */
233 static void ct_xfitimer_check_period(struct ct_timer
*atimer
)
235 struct ct_timer_instance
*ti
;
238 spin_lock_irqsave(&atimer
->list_lock
, flags
);
239 list_for_each_entry(ti
, &atimer
->instance_head
, instance_list
) {
240 if (ti
->running
&& ti
->need_update
) {
242 ti
->apcm
->interrupt(ti
->apcm
);
245 spin_unlock_irqrestore(&atimer
->list_lock
, flags
);
248 /* Handle timer-interrupt */
249 static void ct_xfitimer_callback(struct ct_timer
*atimer
)
254 spin_lock_irqsave(&atimer
->lock
, flags
);
255 atimer
->irq_handling
= 1;
257 update
= ct_xfitimer_reprogram(atimer
, 1);
258 spin_unlock(&atimer
->lock
);
260 ct_xfitimer_check_period(atimer
);
261 spin_lock(&atimer
->lock
);
262 } while (atimer
->reprogram
);
263 atimer
->irq_handling
= 0;
264 spin_unlock_irqrestore(&atimer
->lock
, flags
);
267 static void ct_xfitimer_prepare(struct ct_timer_instance
*ti
)
269 ti
->frag_count
= ti
->substream
->runtime
->period_size
;
275 /* start/stop the timer */
276 static void ct_xfitimer_update(struct ct_timer
*atimer
)
280 spin_lock_irqsave(&atimer
->lock
, flags
);
281 if (atimer
->irq_handling
) {
282 /* reached from IRQ handler; let it handle later */
283 atimer
->reprogram
= 1;
284 spin_unlock_irqrestore(&atimer
->lock
, flags
);
288 ct_xfitimer_irq_stop(atimer
);
289 ct_xfitimer_reprogram(atimer
, 0);
290 spin_unlock_irqrestore(&atimer
->lock
, flags
);
293 static void ct_xfitimer_start(struct ct_timer_instance
*ti
)
295 struct ct_timer
*atimer
= ti
->timer_base
;
298 spin_lock_irqsave(&atimer
->lock
, flags
);
299 if (list_empty(&ti
->running_list
))
300 atimer
->wc
= ct_xfitimer_get_wc(atimer
);
303 list_add(&ti
->running_list
, &atimer
->running_head
);
304 spin_unlock_irqrestore(&atimer
->lock
, flags
);
305 ct_xfitimer_update(atimer
);
308 static void ct_xfitimer_stop(struct ct_timer_instance
*ti
)
310 struct ct_timer
*atimer
= ti
->timer_base
;
313 spin_lock_irqsave(&atimer
->lock
, flags
);
314 list_del_init(&ti
->running_list
);
316 spin_unlock_irqrestore(&atimer
->lock
, flags
);
317 ct_xfitimer_update(atimer
);
320 static void ct_xfitimer_free_global(struct ct_timer
*atimer
)
322 ct_xfitimer_irq_stop(atimer
);
325 static struct ct_timer_ops ct_xfitimer_ops
= {
326 .prepare
= ct_xfitimer_prepare
,
327 .start
= ct_xfitimer_start
,
328 .stop
= ct_xfitimer_stop
,
329 .interrupt
= ct_xfitimer_callback
,
330 .free_global
= ct_xfitimer_free_global
,
337 struct ct_timer_instance
*
338 ct_timer_instance_new(struct ct_timer
*atimer
, struct ct_atc_pcm
*apcm
)
340 struct ct_timer_instance
*ti
;
342 ti
= kzalloc(sizeof(*ti
), GFP_KERNEL
);
345 spin_lock_init(&ti
->lock
);
346 INIT_LIST_HEAD(&ti
->instance_list
);
347 INIT_LIST_HEAD(&ti
->running_list
);
348 ti
->timer_base
= atimer
;
350 ti
->substream
= apcm
->substream
;
351 if (atimer
->ops
->init
)
352 atimer
->ops
->init(ti
);
354 spin_lock_irq(&atimer
->list_lock
);
355 list_add(&ti
->instance_list
, &atimer
->instance_head
);
356 spin_unlock_irq(&atimer
->list_lock
);
361 void ct_timer_prepare(struct ct_timer_instance
*ti
)
363 if (ti
->timer_base
->ops
->prepare
)
364 ti
->timer_base
->ops
->prepare(ti
);
369 void ct_timer_start(struct ct_timer_instance
*ti
)
371 struct ct_timer
*atimer
= ti
->timer_base
;
372 atimer
->ops
->start(ti
);
375 void ct_timer_stop(struct ct_timer_instance
*ti
)
377 struct ct_timer
*atimer
= ti
->timer_base
;
378 atimer
->ops
->stop(ti
);
381 void ct_timer_instance_free(struct ct_timer_instance
*ti
)
383 struct ct_timer
*atimer
= ti
->timer_base
;
385 atimer
->ops
->stop(ti
); /* to be sure */
386 if (atimer
->ops
->free_instance
)
387 atimer
->ops
->free_instance(ti
);
389 spin_lock_irq(&atimer
->list_lock
);
390 list_del(&ti
->instance_list
);
391 spin_unlock_irq(&atimer
->list_lock
);
400 static void ct_timer_interrupt(void *data
, unsigned int status
)
402 struct ct_timer
*timer
= data
;
404 /* Interval timer interrupt */
405 if ((status
& IT_INT
) && timer
->ops
->interrupt
)
406 timer
->ops
->interrupt(timer
);
409 struct ct_timer
*ct_timer_new(struct ct_atc
*atc
)
411 struct ct_timer
*atimer
;
414 atimer
= kzalloc(sizeof(*atimer
), GFP_KERNEL
);
417 spin_lock_init(&atimer
->lock
);
418 spin_lock_init(&atimer
->list_lock
);
419 INIT_LIST_HEAD(&atimer
->instance_head
);
420 INIT_LIST_HEAD(&atimer
->running_head
);
423 if (!use_system_timer
&& hw
->set_timer_irq
) {
424 snd_printd(KERN_INFO
"ctxfi: Use xfi-native timer\n");
425 atimer
->ops
= &ct_xfitimer_ops
;
426 hw
->irq_callback_data
= atimer
;
427 hw
->irq_callback
= ct_timer_interrupt
;
429 snd_printd(KERN_INFO
"ctxfi: Use system timer\n");
430 atimer
->ops
= &ct_systimer_ops
;
435 void ct_timer_free(struct ct_timer
*atimer
)
437 struct hw
*hw
= atimer
->atc
->hw
;
438 hw
->irq_callback
= NULL
;
439 if (atimer
->ops
->free_global
)
440 atimer
->ops
->free_global(atimer
);