diff options
Diffstat (limited to 'sound/pci/ctxfi/cttimer.c')
| -rw-r--r-- | sound/pci/ctxfi/cttimer.c | 18 |
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 | */ |
| 183 | static int ct_xfitimer_reprogram(struct ct_timer *atimer) | 183 | static 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) | |||
| 265 | static void ct_xfitimer_prepare(struct ct_timer_instance *ti) | 267 | static 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) | |||
| 273 | static void ct_xfitimer_update(struct ct_timer *atimer) | 276 | static 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 | ||
| 293 | static void ct_xfitimer_start(struct ct_timer_instance *ti) | 293 | static 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 | } |
