root/sound/core/seq/seq_timer.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. snd_seq_timer_set_tick_resolution
  2. snd_seq_timer_new
  3. snd_seq_timer_delete
  4. snd_seq_timer_defaults
  5. seq_timer_reset
  6. snd_seq_timer_reset
  7. snd_seq_timer_interrupt
  8. snd_seq_timer_set_tempo
  9. snd_seq_timer_set_tempo_ppq
  10. snd_seq_timer_set_position_tick
  11. snd_seq_timer_set_position_time
  12. snd_seq_timer_set_skew
  13. snd_seq_timer_open
  14. snd_seq_timer_close
  15. seq_timer_stop
  16. snd_seq_timer_stop
  17. initialize_timer
  18. seq_timer_start
  19. snd_seq_timer_start
  20. seq_timer_continue
  21. snd_seq_timer_continue
  22. snd_seq_timer_get_cur_time
  23. snd_seq_timer_get_cur_tick
  24. snd_seq_info_timer_read

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *   ALSA sequencer Timer
   4  *   Copyright (c) 1998-1999 by Frank van de Pol <fvdpol@coil.demon.nl>
   5  *                              Jaroslav Kysela <perex@perex.cz>
   6  */
   7 
   8 #include <sound/core.h>
   9 #include <linux/slab.h>
  10 #include "seq_timer.h"
  11 #include "seq_queue.h"
  12 #include "seq_info.h"
  13 
  14 /* allowed sequencer timer frequencies, in Hz */
  15 #define MIN_FREQUENCY           10
  16 #define MAX_FREQUENCY           6250
  17 #define DEFAULT_FREQUENCY       1000
  18 
  19 #define SKEW_BASE       0x10000 /* 16bit shift */
  20 
  21 static void snd_seq_timer_set_tick_resolution(struct snd_seq_timer *tmr)
  22 {
  23         if (tmr->tempo < 1000000)
  24                 tmr->tick.resolution = (tmr->tempo * 1000) / tmr->ppq;
  25         else {
  26                 /* might overflow.. */
  27                 unsigned int s;
  28                 s = tmr->tempo % tmr->ppq;
  29                 s = (s * 1000) / tmr->ppq;
  30                 tmr->tick.resolution = (tmr->tempo / tmr->ppq) * 1000;
  31                 tmr->tick.resolution += s;
  32         }
  33         if (tmr->tick.resolution <= 0)
  34                 tmr->tick.resolution = 1;
  35         snd_seq_timer_update_tick(&tmr->tick, 0);
  36 }
  37 
  38 /* create new timer (constructor) */
  39 struct snd_seq_timer *snd_seq_timer_new(void)
  40 {
  41         struct snd_seq_timer *tmr;
  42         
  43         tmr = kzalloc(sizeof(*tmr), GFP_KERNEL);
  44         if (!tmr)
  45                 return NULL;
  46         spin_lock_init(&tmr->lock);
  47 
  48         /* reset setup to defaults */
  49         snd_seq_timer_defaults(tmr);
  50         
  51         /* reset time */
  52         snd_seq_timer_reset(tmr);
  53         
  54         return tmr;
  55 }
  56 
  57 /* delete timer (destructor) */
  58 void snd_seq_timer_delete(struct snd_seq_timer **tmr)
  59 {
  60         struct snd_seq_timer *t = *tmr;
  61         *tmr = NULL;
  62 
  63         if (t == NULL) {
  64                 pr_debug("ALSA: seq: snd_seq_timer_delete() called with NULL timer\n");
  65                 return;
  66         }
  67         t->running = 0;
  68 
  69         /* reset time */
  70         snd_seq_timer_stop(t);
  71         snd_seq_timer_reset(t);
  72 
  73         kfree(t);
  74 }
  75 
  76 void snd_seq_timer_defaults(struct snd_seq_timer * tmr)
  77 {
  78         unsigned long flags;
  79 
  80         spin_lock_irqsave(&tmr->lock, flags);
  81         /* setup defaults */
  82         tmr->ppq = 96;          /* 96 PPQ */
  83         tmr->tempo = 500000;    /* 120 BPM */
  84         snd_seq_timer_set_tick_resolution(tmr);
  85         tmr->running = 0;
  86 
  87         tmr->type = SNDRV_SEQ_TIMER_ALSA;
  88         tmr->alsa_id.dev_class = seq_default_timer_class;
  89         tmr->alsa_id.dev_sclass = seq_default_timer_sclass;
  90         tmr->alsa_id.card = seq_default_timer_card;
  91         tmr->alsa_id.device = seq_default_timer_device;
  92         tmr->alsa_id.subdevice = seq_default_timer_subdevice;
  93         tmr->preferred_resolution = seq_default_timer_resolution;
  94 
  95         tmr->skew = tmr->skew_base = SKEW_BASE;
  96         spin_unlock_irqrestore(&tmr->lock, flags);
  97 }
  98 
  99 static void seq_timer_reset(struct snd_seq_timer *tmr)
 100 {
 101         /* reset time & songposition */
 102         tmr->cur_time.tv_sec = 0;
 103         tmr->cur_time.tv_nsec = 0;
 104 
 105         tmr->tick.cur_tick = 0;
 106         tmr->tick.fraction = 0;
 107 }
 108 
 109 void snd_seq_timer_reset(struct snd_seq_timer *tmr)
 110 {
 111         unsigned long flags;
 112 
 113         spin_lock_irqsave(&tmr->lock, flags);
 114         seq_timer_reset(tmr);
 115         spin_unlock_irqrestore(&tmr->lock, flags);
 116 }
 117 
 118 
 119 /* called by timer interrupt routine. the period time since previous invocation is passed */
 120 static void snd_seq_timer_interrupt(struct snd_timer_instance *timeri,
 121                                     unsigned long resolution,
 122                                     unsigned long ticks)
 123 {
 124         unsigned long flags;
 125         struct snd_seq_queue *q = timeri->callback_data;
 126         struct snd_seq_timer *tmr;
 127 
 128         if (q == NULL)
 129                 return;
 130         tmr = q->timer;
 131         if (tmr == NULL)
 132                 return;
 133         spin_lock_irqsave(&tmr->lock, flags);
 134         if (!tmr->running) {
 135                 spin_unlock_irqrestore(&tmr->lock, flags);
 136                 return;
 137         }
 138 
 139         resolution *= ticks;
 140         if (tmr->skew != tmr->skew_base) {
 141                 /* FIXME: assuming skew_base = 0x10000 */
 142                 resolution = (resolution >> 16) * tmr->skew +
 143                         (((resolution & 0xffff) * tmr->skew) >> 16);
 144         }
 145 
 146         /* update timer */
 147         snd_seq_inc_time_nsec(&tmr->cur_time, resolution);
 148 
 149         /* calculate current tick */
 150         snd_seq_timer_update_tick(&tmr->tick, resolution);
 151 
 152         /* register actual time of this timer update */
 153         ktime_get_ts64(&tmr->last_update);
 154 
 155         spin_unlock_irqrestore(&tmr->lock, flags);
 156 
 157         /* check queues and dispatch events */
 158         snd_seq_check_queue(q, 1, 0);
 159 }
 160 
 161 /* set current tempo */
 162 int snd_seq_timer_set_tempo(struct snd_seq_timer * tmr, int tempo)
 163 {
 164         unsigned long flags;
 165 
 166         if (snd_BUG_ON(!tmr))
 167                 return -EINVAL;
 168         if (tempo <= 0)
 169                 return -EINVAL;
 170         spin_lock_irqsave(&tmr->lock, flags);
 171         if ((unsigned int)tempo != tmr->tempo) {
 172                 tmr->tempo = tempo;
 173                 snd_seq_timer_set_tick_resolution(tmr);
 174         }
 175         spin_unlock_irqrestore(&tmr->lock, flags);
 176         return 0;
 177 }
 178 
 179 /* set current tempo and ppq in a shot */
 180 int snd_seq_timer_set_tempo_ppq(struct snd_seq_timer *tmr, int tempo, int ppq)
 181 {
 182         int changed;
 183         unsigned long flags;
 184 
 185         if (snd_BUG_ON(!tmr))
 186                 return -EINVAL;
 187         if (tempo <= 0 || ppq <= 0)
 188                 return -EINVAL;
 189         spin_lock_irqsave(&tmr->lock, flags);
 190         if (tmr->running && (ppq != tmr->ppq)) {
 191                 /* refuse to change ppq on running timers */
 192                 /* because it will upset the song position (ticks) */
 193                 spin_unlock_irqrestore(&tmr->lock, flags);
 194                 pr_debug("ALSA: seq: cannot change ppq of a running timer\n");
 195                 return -EBUSY;
 196         }
 197         changed = (tempo != tmr->tempo) || (ppq != tmr->ppq);
 198         tmr->tempo = tempo;
 199         tmr->ppq = ppq;
 200         if (changed)
 201                 snd_seq_timer_set_tick_resolution(tmr);
 202         spin_unlock_irqrestore(&tmr->lock, flags);
 203         return 0;
 204 }
 205 
 206 /* set current tick position */
 207 int snd_seq_timer_set_position_tick(struct snd_seq_timer *tmr,
 208                                     snd_seq_tick_time_t position)
 209 {
 210         unsigned long flags;
 211 
 212         if (snd_BUG_ON(!tmr))
 213                 return -EINVAL;
 214 
 215         spin_lock_irqsave(&tmr->lock, flags);
 216         tmr->tick.cur_tick = position;
 217         tmr->tick.fraction = 0;
 218         spin_unlock_irqrestore(&tmr->lock, flags);
 219         return 0;
 220 }
 221 
 222 /* set current real-time position */
 223 int snd_seq_timer_set_position_time(struct snd_seq_timer *tmr,
 224                                     snd_seq_real_time_t position)
 225 {
 226         unsigned long flags;
 227 
 228         if (snd_BUG_ON(!tmr))
 229                 return -EINVAL;
 230 
 231         snd_seq_sanity_real_time(&position);
 232         spin_lock_irqsave(&tmr->lock, flags);
 233         tmr->cur_time = position;
 234         spin_unlock_irqrestore(&tmr->lock, flags);
 235         return 0;
 236 }
 237 
 238 /* set timer skew */
 239 int snd_seq_timer_set_skew(struct snd_seq_timer *tmr, unsigned int skew,
 240                            unsigned int base)
 241 {
 242         unsigned long flags;
 243 
 244         if (snd_BUG_ON(!tmr))
 245                 return -EINVAL;
 246 
 247         /* FIXME */
 248         if (base != SKEW_BASE) {
 249                 pr_debug("ALSA: seq: invalid skew base 0x%x\n", base);
 250                 return -EINVAL;
 251         }
 252         spin_lock_irqsave(&tmr->lock, flags);
 253         tmr->skew = skew;
 254         spin_unlock_irqrestore(&tmr->lock, flags);
 255         return 0;
 256 }
 257 
 258 int snd_seq_timer_open(struct snd_seq_queue *q)
 259 {
 260         struct snd_timer_instance *t;
 261         struct snd_seq_timer *tmr;
 262         char str[32];
 263         int err;
 264 
 265         tmr = q->timer;
 266         if (snd_BUG_ON(!tmr))
 267                 return -EINVAL;
 268         if (tmr->timeri)
 269                 return -EBUSY;
 270         sprintf(str, "sequencer queue %i", q->queue);
 271         if (tmr->type != SNDRV_SEQ_TIMER_ALSA)  /* standard ALSA timer */
 272                 return -EINVAL;
 273         if (tmr->alsa_id.dev_class != SNDRV_TIMER_CLASS_SLAVE)
 274                 tmr->alsa_id.dev_sclass = SNDRV_TIMER_SCLASS_SEQUENCER;
 275         err = snd_timer_open(&t, str, &tmr->alsa_id, q->queue);
 276         if (err < 0 && tmr->alsa_id.dev_class != SNDRV_TIMER_CLASS_SLAVE) {
 277                 if (tmr->alsa_id.dev_class != SNDRV_TIMER_CLASS_GLOBAL ||
 278                     tmr->alsa_id.device != SNDRV_TIMER_GLOBAL_SYSTEM) {
 279                         struct snd_timer_id tid;
 280                         memset(&tid, 0, sizeof(tid));
 281                         tid.dev_class = SNDRV_TIMER_CLASS_GLOBAL;
 282                         tid.dev_sclass = SNDRV_TIMER_SCLASS_SEQUENCER;
 283                         tid.card = -1;
 284                         tid.device = SNDRV_TIMER_GLOBAL_SYSTEM;
 285                         err = snd_timer_open(&t, str, &tid, q->queue);
 286                 }
 287         }
 288         if (err < 0) {
 289                 pr_err("ALSA: seq fatal error: cannot create timer (%i)\n", err);
 290                 return err;
 291         }
 292         t->callback = snd_seq_timer_interrupt;
 293         t->callback_data = q;
 294         t->flags |= SNDRV_TIMER_IFLG_AUTO;
 295         spin_lock_irq(&tmr->lock);
 296         tmr->timeri = t;
 297         spin_unlock_irq(&tmr->lock);
 298         return 0;
 299 }
 300 
 301 int snd_seq_timer_close(struct snd_seq_queue *q)
 302 {
 303         struct snd_seq_timer *tmr;
 304         struct snd_timer_instance *t;
 305         
 306         tmr = q->timer;
 307         if (snd_BUG_ON(!tmr))
 308                 return -EINVAL;
 309         spin_lock_irq(&tmr->lock);
 310         t = tmr->timeri;
 311         tmr->timeri = NULL;
 312         spin_unlock_irq(&tmr->lock);
 313         if (t)
 314                 snd_timer_close(t);
 315         return 0;
 316 }
 317 
 318 static int seq_timer_stop(struct snd_seq_timer *tmr)
 319 {
 320         if (! tmr->timeri)
 321                 return -EINVAL;
 322         if (!tmr->running)
 323                 return 0;
 324         tmr->running = 0;
 325         snd_timer_pause(tmr->timeri);
 326         return 0;
 327 }
 328 
 329 int snd_seq_timer_stop(struct snd_seq_timer *tmr)
 330 {
 331         unsigned long flags;
 332         int err;
 333 
 334         spin_lock_irqsave(&tmr->lock, flags);
 335         err = seq_timer_stop(tmr);
 336         spin_unlock_irqrestore(&tmr->lock, flags);
 337         return err;
 338 }
 339 
 340 static int initialize_timer(struct snd_seq_timer *tmr)
 341 {
 342         struct snd_timer *t;
 343         unsigned long freq;
 344 
 345         t = tmr->timeri->timer;
 346         if (!t)
 347                 return -EINVAL;
 348 
 349         freq = tmr->preferred_resolution;
 350         if (!freq)
 351                 freq = DEFAULT_FREQUENCY;
 352         else if (freq < MIN_FREQUENCY)
 353                 freq = MIN_FREQUENCY;
 354         else if (freq > MAX_FREQUENCY)
 355                 freq = MAX_FREQUENCY;
 356 
 357         tmr->ticks = 1;
 358         if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE)) {
 359                 unsigned long r = snd_timer_resolution(tmr->timeri);
 360                 if (r) {
 361                         tmr->ticks = (unsigned int)(1000000000uL / (r * freq));
 362                         if (! tmr->ticks)
 363                                 tmr->ticks = 1;
 364                 }
 365         }
 366         tmr->initialized = 1;
 367         return 0;
 368 }
 369 
 370 static int seq_timer_start(struct snd_seq_timer *tmr)
 371 {
 372         if (! tmr->timeri)
 373                 return -EINVAL;
 374         if (tmr->running)
 375                 seq_timer_stop(tmr);
 376         seq_timer_reset(tmr);
 377         if (initialize_timer(tmr) < 0)
 378                 return -EINVAL;
 379         snd_timer_start(tmr->timeri, tmr->ticks);
 380         tmr->running = 1;
 381         ktime_get_ts64(&tmr->last_update);
 382         return 0;
 383 }
 384 
 385 int snd_seq_timer_start(struct snd_seq_timer *tmr)
 386 {
 387         unsigned long flags;
 388         int err;
 389 
 390         spin_lock_irqsave(&tmr->lock, flags);
 391         err = seq_timer_start(tmr);
 392         spin_unlock_irqrestore(&tmr->lock, flags);
 393         return err;
 394 }
 395 
 396 static int seq_timer_continue(struct snd_seq_timer *tmr)
 397 {
 398         if (! tmr->timeri)
 399                 return -EINVAL;
 400         if (tmr->running)
 401                 return -EBUSY;
 402         if (! tmr->initialized) {
 403                 seq_timer_reset(tmr);
 404                 if (initialize_timer(tmr) < 0)
 405                         return -EINVAL;
 406         }
 407         snd_timer_start(tmr->timeri, tmr->ticks);
 408         tmr->running = 1;
 409         ktime_get_ts64(&tmr->last_update);
 410         return 0;
 411 }
 412 
 413 int snd_seq_timer_continue(struct snd_seq_timer *tmr)
 414 {
 415         unsigned long flags;
 416         int err;
 417 
 418         spin_lock_irqsave(&tmr->lock, flags);
 419         err = seq_timer_continue(tmr);
 420         spin_unlock_irqrestore(&tmr->lock, flags);
 421         return err;
 422 }
 423 
 424 /* return current 'real' time. use timeofday() to get better granularity. */
 425 snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr,
 426                                                bool adjust_ktime)
 427 {
 428         snd_seq_real_time_t cur_time;
 429         unsigned long flags;
 430 
 431         spin_lock_irqsave(&tmr->lock, flags);
 432         cur_time = tmr->cur_time;
 433         if (adjust_ktime && tmr->running) {
 434                 struct timespec64 tm;
 435 
 436                 ktime_get_ts64(&tm);
 437                 tm = timespec64_sub(tm, tmr->last_update);
 438                 cur_time.tv_nsec += tm.tv_nsec;
 439                 cur_time.tv_sec += tm.tv_sec;
 440                 snd_seq_sanity_real_time(&cur_time);
 441         }
 442         spin_unlock_irqrestore(&tmr->lock, flags);
 443         return cur_time;        
 444 }
 445 
 446 /* TODO: use interpolation on tick queue (will only be useful for very
 447  high PPQ values) */
 448 snd_seq_tick_time_t snd_seq_timer_get_cur_tick(struct snd_seq_timer *tmr)
 449 {
 450         snd_seq_tick_time_t cur_tick;
 451         unsigned long flags;
 452 
 453         spin_lock_irqsave(&tmr->lock, flags);
 454         cur_tick = tmr->tick.cur_tick;
 455         spin_unlock_irqrestore(&tmr->lock, flags);
 456         return cur_tick;
 457 }
 458 
 459 
 460 #ifdef CONFIG_SND_PROC_FS
 461 /* exported to seq_info.c */
 462 void snd_seq_info_timer_read(struct snd_info_entry *entry,
 463                              struct snd_info_buffer *buffer)
 464 {
 465         int idx;
 466         struct snd_seq_queue *q;
 467         struct snd_seq_timer *tmr;
 468         struct snd_timer_instance *ti;
 469         unsigned long resolution;
 470         
 471         for (idx = 0; idx < SNDRV_SEQ_MAX_QUEUES; idx++) {
 472                 q = queueptr(idx);
 473                 if (q == NULL)
 474                         continue;
 475                 mutex_lock(&q->timer_mutex);
 476                 tmr = q->timer;
 477                 if (!tmr)
 478                         goto unlock;
 479                 ti = tmr->timeri;
 480                 if (!ti)
 481                         goto unlock;
 482                 snd_iprintf(buffer, "Timer for queue %i : %s\n", q->queue, ti->timer->name);
 483                 resolution = snd_timer_resolution(ti) * tmr->ticks;
 484                 snd_iprintf(buffer, "  Period time : %lu.%09lu\n", resolution / 1000000000, resolution % 1000000000);
 485                 snd_iprintf(buffer, "  Skew : %u / %u\n", tmr->skew, tmr->skew_base);
 486 unlock:
 487                 mutex_unlock(&q->timer_mutex);
 488                 queuefree(q);
 489         }
 490 }
 491 #endif /* CONFIG_SND_PROC_FS */
 492 

/* [<][>][^][v][top][bottom][index][help] */