3 **********************************************************************
5 * Copyright (C) 1999, 2000 Creative Labs, inc.
7 **********************************************************************
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public
20 * License along with this program; if not, write to the Free
21 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
24 **********************************************************************
27 /* 3/6/2000 Improved support for different timer delays Rui Sousa */
29 /* 4/3/2000 Implemented timer list using list.h Rui Sousa */
36 /* Try to schedule only once per fragment */
38 void emu10k1_timer_irqhandler(struct emu10k1_card
*card
)
41 struct list_head
*entry
;
43 spin_lock(&card
->timer_lock
);
45 list_for_each(entry
, &card
->timers
) {
46 t
= list_entry(entry
, struct emu_timer
, list
);
48 if (t
->state
& TIMER_STATE_ACTIVE
) {
50 if (t
->count
== t
->count_max
) {
52 tasklet_hi_schedule(&t
->tasklet
);
57 spin_unlock(&card
->timer_lock
);
62 void emu10k1_timer_install(struct emu10k1_card
*card
, struct emu_timer
*timer
, u16 delay
)
65 struct list_head
*entry
;
72 timer
->state
= TIMER_STATE_INSTALLED
;
74 spin_lock_irqsave(&card
->timer_lock
, flags
);
76 timer
->count_max
= timer
->delay
/ (card
->timer_delay
< 1024 ? card
->timer_delay
: 1024);
77 timer
->count
= timer
->count_max
- 1;
79 list_add(&timer
->list
, &card
->timers
);
81 if (card
->timer_delay
> delay
) {
82 if (card
->timer_delay
== TIMER_STOPPED
)
83 emu10k1_irq_enable(card
, INTE_INTERVALTIMERENB
);
85 card
->timer_delay
= delay
;
86 delay
= (delay
< 1024 ? delay
: 1024);
88 emu10k1_timer_set(card
, delay
);
90 list_for_each(entry
, &card
->timers
) {
91 t
= list_entry(entry
, struct emu_timer
, list
);
93 t
->count_max
= t
->delay
/ delay
;
94 /* don't want to think much, just force scheduling
95 on the next interrupt */
96 t
->count
= t
->count_max
- 1;
99 DPD(2, "timer rate --> %u\n", delay
);
102 spin_unlock_irqrestore(&card
->timer_lock
, flags
);
107 void emu10k1_timer_uninstall(struct emu10k1_card
*card
, struct emu_timer
*timer
)
110 struct list_head
*entry
;
111 u16 delay
= TIMER_STOPPED
;
114 if (timer
->state
== TIMER_STATE_UNINSTALLED
)
117 spin_lock_irqsave(&card
->timer_lock
, flags
);
119 list_del(&timer
->list
);
121 list_for_each(entry
, &card
->timers
) {
122 t
= list_entry(entry
, struct emu_timer
, list
);
124 if (t
->delay
< delay
)
128 if (card
->timer_delay
!= delay
) {
129 card
->timer_delay
= delay
;
131 if (delay
== TIMER_STOPPED
)
132 emu10k1_irq_disable(card
, INTE_INTERVALTIMERENB
);
134 delay
= (delay
< 1024 ? delay
: 1024);
136 emu10k1_timer_set(card
, delay
);
138 list_for_each(entry
, &card
->timers
) {
139 t
= list_entry(entry
, struct emu_timer
, list
);
141 t
->count_max
= t
->delay
/ delay
;
142 t
->count
= t
->count_max
- 1;
146 DPD(2, "timer rate --> %u\n", delay
);
149 spin_unlock_irqrestore(&card
->timer_lock
, flags
);
151 timer
->state
= TIMER_STATE_UNINSTALLED
;
156 void emu10k1_timer_enable(struct emu10k1_card
*card
, struct emu_timer
*timer
)
160 spin_lock_irqsave(&card
->timer_lock
, flags
);
161 timer
->state
|= TIMER_STATE_ACTIVE
;
162 spin_unlock_irqrestore(&card
->timer_lock
, flags
);
167 void emu10k1_timer_disable(struct emu10k1_card
*card
, struct emu_timer
*timer
)
171 spin_lock_irqsave(&card
->timer_lock
, flags
);
172 timer
->state
&= ~TIMER_STATE_ACTIVE
;
173 spin_unlock_irqrestore(&card
->timer_lock
, flags
);