1 /* 2 * PCM timer handling on ctxfi 3 * 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. 7 */ 8 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> 14 #include "ctatc.h" 15 #include "cthardware.h" 16 #include "cttimer.h" 17 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, S_IRUGO); 21 22 struct ct_timer_ops { 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 *); 30 }; 31 32 /* timer instance -- assigned to each PCM stream */ 33 struct ct_timer_instance { 34 spinlock_t lock; 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; 45 }; 46 47 /* timer instance manager */ 48 struct ct_timer { 49 spinlock_t lock; /* global timer lock (for xfitimer) */ 50 spinlock_t list_lock; /* lock for instance list */ 51 struct ct_atc *atc; 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 */ 59 }; 60 61 62 /* 63 * system-timer-based updates 64 */ 65 66 static void ct_systimer_callback(unsigned long data) 67 { 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; 74 unsigned long flags; 75 unsigned int position, dist, interval; 76 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; 83 } 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); 89 if (ti->running) 90 mod_timer(&ti->timer, jiffies + interval); 91 spin_unlock_irqrestore(&ti->lock, flags); 92 } 93 94 static void ct_systimer_init(struct ct_timer_instance *ti) 95 { 96 setup_timer(&ti->timer, ct_systimer_callback, 97 (unsigned long)ti); 98 } 99 100 static void ct_systimer_start(struct ct_timer_instance *ti) 101 { 102 struct snd_pcm_runtime *runtime = ti->substream->runtime; 103 unsigned long flags; 104 105 spin_lock_irqsave(&ti->lock, flags); 106 ti->running = 1; 107 mod_timer(&ti->timer, 108 jiffies + (runtime->period_size * HZ + 109 (runtime->rate - 1)) / runtime->rate); 110 spin_unlock_irqrestore(&ti->lock, flags); 111 } 112 113 static void ct_systimer_stop(struct ct_timer_instance *ti) 114 { 115 unsigned long flags; 116 117 spin_lock_irqsave(&ti->lock, flags); 118 ti->running = 0; 119 del_timer(&ti->timer); 120 spin_unlock_irqrestore(&ti->lock, flags); 121 } 122 123 static void ct_systimer_prepare(struct ct_timer_instance *ti) 124 { 125 ct_systimer_stop(ti); 126 try_to_del_timer_sync(&ti->timer); 127 } 128 129 #define ct_systimer_free ct_systimer_prepare 130 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, 137 }; 138 139 140 /* 141 * Handling multiple streams using a global emu20k1 timer irq 142 */ 143 144 #define CT_TIMER_FREQ 48000 145 #define MIN_TICKS 1 146 #define MAX_TICKS ((1 << 13) - 1) 147 148 static void ct_xfitimer_irq_rearm(struct ct_timer *atimer, int ticks) 149 { 150 struct hw *hw = atimer->atc->hw; 151 if (ticks > MAX_TICKS) 152 ticks = MAX_TICKS; 153 hw->set_timer_tick(hw, ticks); 154 if (!atimer->running) 155 hw->set_timer_irq(hw, 1); 156 atimer->running = 1; 157 } 158 159 static void ct_xfitimer_irq_stop(struct ct_timer *atimer) 160 { 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); 165 atimer->running = 0; 166 } 167 } 168 169 static inline unsigned int ct_xfitimer_get_wc(struct ct_timer *atimer) 170 { 171 struct hw *hw = atimer->atc->hw; 172 return hw->get_wc(hw); 173 } 174 175 /* 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 180 * 181 * call this inside the lock and irq disabled 182 */ 183 static int ct_xfitimer_reprogram(struct ct_timer *atimer, int can_update) 184 { 185 struct ct_timer_instance *ti; 186 unsigned int min_intr = (unsigned int)-1; 187 int updates = 0; 188 unsigned int wc, diff; 189 190 if (list_empty(&atimer->running_head)) { 191 ct_xfitimer_irq_stop(atimer); 192 atimer->reprogram = 0; /* clear flag */ 193 return 0; 194 } 195 196 wc = ct_xfitimer_get_wc(atimer); 197 diff = wc - atimer->wc; 198 atimer->wc = wc; 199 list_for_each_entry(ti, &atimer->running_head, running_list) { 200 if (ti->frag_count > diff) 201 ti->frag_count -= diff; 202 else { 203 unsigned int pos; 204 unsigned int period_size, rate; 205 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) { 210 ti->need_update = 1; 211 ti->position = pos; 212 updates++; 213 } 214 pos %= period_size; 215 pos = period_size - pos; 216 ti->frag_count = div_u64((u64)pos * CT_TIMER_FREQ + 217 rate - 1, rate); 218 } 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; 223 } 224 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 */ 229 return updates; 230 } 231 232 /* look through the instance list and call period_elapsed if needed */ 233 static void ct_xfitimer_check_period(struct ct_timer *atimer) 234 { 235 struct ct_timer_instance *ti; 236 unsigned long flags; 237 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) { 241 ti->need_update = 0; 242 ti->apcm->interrupt(ti->apcm); 243 } 244 } 245 spin_unlock_irqrestore(&atimer->list_lock, flags); 246 } 247 248 /* Handle timer-interrupt */ 249 static void ct_xfitimer_callback(struct ct_timer *atimer) 250 { 251 int update; 252 unsigned long flags; 253 254 spin_lock_irqsave(&atimer->lock, flags); 255 atimer->irq_handling = 1; 256 do { 257 update = ct_xfitimer_reprogram(atimer, 1); 258 spin_unlock(&atimer->lock); 259 if (update) 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); 265 } 266 267 static void ct_xfitimer_prepare(struct ct_timer_instance *ti) 268 { 269 ti->frag_count = ti->substream->runtime->period_size; 270 ti->running = 0; 271 ti->need_update = 0; 272 } 273 274 275 /* start/stop the timer */ 276 static void ct_xfitimer_update(struct ct_timer *atimer) 277 { 278 unsigned long flags; 279 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); 285 return; 286 } 287 288 ct_xfitimer_irq_stop(atimer); 289 ct_xfitimer_reprogram(atimer, 0); 290 spin_unlock_irqrestore(&atimer->lock, flags); 291 } 292 293 static void ct_xfitimer_start(struct ct_timer_instance *ti) 294 { 295 struct ct_timer *atimer = ti->timer_base; 296 unsigned long flags; 297 298 spin_lock_irqsave(&atimer->lock, flags); 299 if (list_empty(&ti->running_list)) 300 atimer->wc = ct_xfitimer_get_wc(atimer); 301 ti->running = 1; 302 ti->need_update = 0; 303 list_add(&ti->running_list, &atimer->running_head); 304 spin_unlock_irqrestore(&atimer->lock, flags); 305 ct_xfitimer_update(atimer); 306 } 307 308 static void ct_xfitimer_stop(struct ct_timer_instance *ti) 309 { 310 struct ct_timer *atimer = ti->timer_base; 311 unsigned long flags; 312 313 spin_lock_irqsave(&atimer->lock, flags); 314 list_del_init(&ti->running_list); 315 ti->running = 0; 316 spin_unlock_irqrestore(&atimer->lock, flags); 317 ct_xfitimer_update(atimer); 318 } 319 320 static void ct_xfitimer_free_global(struct ct_timer *atimer) 321 { 322 ct_xfitimer_irq_stop(atimer); 323 } 324 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, 331 }; 332 333 /* 334 * timer instance 335 */ 336 337 struct ct_timer_instance * 338 ct_timer_instance_new(struct ct_timer *atimer, struct ct_atc_pcm *apcm) 339 { 340 struct ct_timer_instance *ti; 341 342 ti = kzalloc(sizeof(*ti), GFP_KERNEL); 343 if (!ti) 344 return NULL; 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; 349 ti->apcm = apcm; 350 ti->substream = apcm->substream; 351 if (atimer->ops->init) 352 atimer->ops->init(ti); 353 354 spin_lock_irq(&atimer->list_lock); 355 list_add(&ti->instance_list, &atimer->instance_head); 356 spin_unlock_irq(&atimer->list_lock); 357 358 return ti; 359 } 360 361 void ct_timer_prepare(struct ct_timer_instance *ti) 362 { 363 if (ti->timer_base->ops->prepare) 364 ti->timer_base->ops->prepare(ti); 365 ti->position = 0; 366 ti->running = 0; 367 } 368 369 void ct_timer_start(struct ct_timer_instance *ti) 370 { 371 struct ct_timer *atimer = ti->timer_base; 372 atimer->ops->start(ti); 373 } 374 375 void ct_timer_stop(struct ct_timer_instance *ti) 376 { 377 struct ct_timer *atimer = ti->timer_base; 378 atimer->ops->stop(ti); 379 } 380 381 void ct_timer_instance_free(struct ct_timer_instance *ti) 382 { 383 struct ct_timer *atimer = ti->timer_base; 384 385 atimer->ops->stop(ti); /* to be sure */ 386 if (atimer->ops->free_instance) 387 atimer->ops->free_instance(ti); 388 389 spin_lock_irq(&atimer->list_lock); 390 list_del(&ti->instance_list); 391 spin_unlock_irq(&atimer->list_lock); 392 393 kfree(ti); 394 } 395 396 /* 397 * timer manager 398 */ 399 400 static void ct_timer_interrupt(void *data, unsigned int status) 401 { 402 struct ct_timer *timer = data; 403 404 /* Interval timer interrupt */ 405 if ((status & IT_INT) && timer->ops->interrupt) 406 timer->ops->interrupt(timer); 407 } 408 409 struct ct_timer *ct_timer_new(struct ct_atc *atc) 410 { 411 struct ct_timer *atimer; 412 struct hw *hw; 413 414 atimer = kzalloc(sizeof(*atimer), GFP_KERNEL); 415 if (!atimer) 416 return NULL; 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); 421 atimer->atc = atc; 422 hw = atc->hw; 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; 428 } else { 429 snd_printd(KERN_INFO "ctxfi: Use system timer\n"); 430 atimer->ops = &ct_systimer_ops; 431 } 432 return atimer; 433 } 434 435 void ct_timer_free(struct ct_timer *atimer) 436 { 437 struct hw *hw = atimer->atc->hw; 438 hw->irq_callback = NULL; 439 if (atimer->ops->free_global) 440 atimer->ops->free_global(atimer); 441 kfree(atimer); 442 } 443 444