aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/ctxfi/cttimer.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/ctxfi/cttimer.c')
-rw-r--r--sound/pci/ctxfi/cttimer.c18
1 files changed, 10 insertions, 8 deletions
diff --git a/sound/pci/ctxfi/cttimer.c b/sound/pci/ctxfi/cttimer.c
index 779c6c3591a5..93b0aedc36d4 100644
--- a/sound/pci/ctxfi/cttimer.c
+++ b/sound/pci/ctxfi/cttimer.c
@@ -180,7 +180,7 @@ static inline unsigned int ct_xfitimer_get_wc(struct ct_timer *atimer)
180 * 180 *
181 * call this inside the lock and irq disabled 181 * call this inside the lock and irq disabled
182 */ 182 */
183static int ct_xfitimer_reprogram(struct ct_timer *atimer) 183static int ct_xfitimer_reprogram(struct ct_timer *atimer, int can_update)
184{ 184{
185 struct ct_timer_instance *ti; 185 struct ct_timer_instance *ti;
186 unsigned int min_intr = (unsigned int)-1; 186 unsigned int min_intr = (unsigned int)-1;
@@ -216,6 +216,8 @@ static int ct_xfitimer_reprogram(struct ct_timer *atimer)
216 ti->frag_count = div_u64((u64)pos * CT_TIMER_FREQ + 216 ti->frag_count = div_u64((u64)pos * CT_TIMER_FREQ +
217 rate - 1, rate); 217 rate - 1, rate);
218 } 218 }
219 if (ti->need_update && !can_update)
220 min_intr = 0; /* pending to the next irq */
219 if (ti->frag_count < min_intr) 221 if (ti->frag_count < min_intr)
220 min_intr = ti->frag_count; 222 min_intr = ti->frag_count;
221 } 223 }
@@ -235,7 +237,7 @@ static void ct_xfitimer_check_period(struct ct_timer *atimer)
235 237
236 spin_lock_irqsave(&atimer->list_lock, flags); 238 spin_lock_irqsave(&atimer->list_lock, flags);
237 list_for_each_entry(ti, &atimer->instance_head, instance_list) { 239 list_for_each_entry(ti, &atimer->instance_head, instance_list) {
238 if (ti->need_update) { 240 if (ti->running && ti->need_update) {
239 ti->need_update = 0; 241 ti->need_update = 0;
240 ti->apcm->interrupt(ti->apcm); 242 ti->apcm->interrupt(ti->apcm);
241 } 243 }
@@ -252,7 +254,7 @@ static void ct_xfitimer_callback(struct ct_timer *atimer)
252 spin_lock_irqsave(&atimer->lock, flags); 254 spin_lock_irqsave(&atimer->lock, flags);
253 atimer->irq_handling = 1; 255 atimer->irq_handling = 1;
254 do { 256 do {
255 update = ct_xfitimer_reprogram(atimer); 257 update = ct_xfitimer_reprogram(atimer, 1);
256 spin_unlock(&atimer->lock); 258 spin_unlock(&atimer->lock);
257 if (update) 259 if (update)
258 ct_xfitimer_check_period(atimer); 260 ct_xfitimer_check_period(atimer);
@@ -265,6 +267,7 @@ static void ct_xfitimer_callback(struct ct_timer *atimer)
265static void ct_xfitimer_prepare(struct ct_timer_instance *ti) 267static void ct_xfitimer_prepare(struct ct_timer_instance *ti)
266{ 268{
267 ti->frag_count = ti->substream->runtime->period_size; 269 ti->frag_count = ti->substream->runtime->period_size;
270 ti->running = 0;
268 ti->need_update = 0; 271 ti->need_update = 0;
269} 272}
270 273
@@ -273,7 +276,6 @@ static void ct_xfitimer_prepare(struct ct_timer_instance *ti)
273static void ct_xfitimer_update(struct ct_timer *atimer) 276static void ct_xfitimer_update(struct ct_timer *atimer)
274{ 277{
275 unsigned long flags; 278 unsigned long flags;
276 int update;
277 279
278 spin_lock_irqsave(&atimer->lock, flags); 280 spin_lock_irqsave(&atimer->lock, flags);
279 if (atimer->irq_handling) { 281 if (atimer->irq_handling) {
@@ -284,10 +286,8 @@ static void ct_xfitimer_update(struct ct_timer *atimer)
284 } 286 }
285 287
286 ct_xfitimer_irq_stop(atimer); 288 ct_xfitimer_irq_stop(atimer);
287 update = ct_xfitimer_reprogram(atimer); 289 ct_xfitimer_reprogram(atimer, 0);
288 spin_unlock_irqrestore(&atimer->lock, flags); 290 spin_unlock_irqrestore(&atimer->lock, flags);
289 if (update)
290 ct_xfitimer_check_period(atimer);
291} 291}
292 292
293static void ct_xfitimer_start(struct ct_timer_instance *ti) 293static void ct_xfitimer_start(struct ct_timer_instance *ti)
@@ -298,6 +298,8 @@ static void ct_xfitimer_start(struct ct_timer_instance *ti)
298 spin_lock_irqsave(&atimer->lock, flags); 298 spin_lock_irqsave(&atimer->lock, flags);
299 if (list_empty(&ti->running_list)) 299 if (list_empty(&ti->running_list))
300 atimer->wc = ct_xfitimer_get_wc(atimer); 300 atimer->wc = ct_xfitimer_get_wc(atimer);
301 ti->running = 1;
302 ti->need_update = 0;
301 list_add(&ti->running_list, &atimer->running_head); 303 list_add(&ti->running_list, &atimer->running_head);
302 spin_unlock_irqrestore(&atimer->lock, flags); 304 spin_unlock_irqrestore(&atimer->lock, flags);
303 ct_xfitimer_update(atimer); 305 ct_xfitimer_update(atimer);
@@ -310,7 +312,7 @@ static void ct_xfitimer_stop(struct ct_timer_instance *ti)
310 312
311 spin_lock_irqsave(&atimer->lock, flags); 313 spin_lock_irqsave(&atimer->lock, flags);
312 list_del_init(&ti->running_list); 314 list_del_init(&ti->running_list);
313 ti->need_update = 0; 315 ti->running = 0;
314 spin_unlock_irqrestore(&atimer->lock, flags); 316 spin_unlock_irqrestore(&atimer->lock, flags);
315 ct_xfitimer_update(atimer); 317 ct_xfitimer_update(atimer);
316} 318}