xref: /openbmc/linux/sound/core/seq/seq_timer.h (revision 8dd06ef34b6e2f41b29fbf5fc1663780f2524285)
11a59d1b8SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  *  ALSA sequencer Timer
41da177e4SLinus Torvalds  *  Copyright (c) 1998-1999 by Frank van de Pol <fvdpol@coil.demon.nl>
51da177e4SLinus Torvalds  */
61da177e4SLinus Torvalds #ifndef __SND_SEQ_TIMER_H
71da177e4SLinus Torvalds #define __SND_SEQ_TIMER_H
81da177e4SLinus Torvalds 
91da177e4SLinus Torvalds #include <sound/timer.h>
101da177e4SLinus Torvalds #include <sound/seq_kernel.h>
111da177e4SLinus Torvalds 
12c7e0b5bfSTakashi Iwai struct snd_seq_timer_tick {
131da177e4SLinus Torvalds 	snd_seq_tick_time_t	cur_tick;	/* current tick */
141da177e4SLinus Torvalds 	unsigned long		resolution;	/* time per tick in nsec */
151da177e4SLinus Torvalds 	unsigned long		fraction;	/* current time per tick in nsec */
16c7e0b5bfSTakashi Iwai };
171da177e4SLinus Torvalds 
18c7e0b5bfSTakashi Iwai struct snd_seq_timer {
191da177e4SLinus Torvalds 	/* ... tempo / offset / running state */
201da177e4SLinus Torvalds 
211da177e4SLinus Torvalds 	unsigned int		running:1,	/* running state of queue */
221da177e4SLinus Torvalds 				initialized:1;	/* timer is initialized */
231da177e4SLinus Torvalds 
241da177e4SLinus Torvalds 	unsigned int		tempo;		/* current tempo, us/tick */
251da177e4SLinus Torvalds 	int			ppq;		/* time resolution, ticks/quarter */
261da177e4SLinus Torvalds 
271da177e4SLinus Torvalds 	snd_seq_real_time_t	cur_time;	/* current time */
28c7e0b5bfSTakashi Iwai 	struct snd_seq_timer_tick	tick;	/* current tick */
291da177e4SLinus Torvalds 	int tick_updated;
301da177e4SLinus Torvalds 
311da177e4SLinus Torvalds 	int			type;		/* timer type */
32c7e0b5bfSTakashi Iwai 	struct snd_timer_id	alsa_id;	/* ALSA's timer ID */
33c7e0b5bfSTakashi Iwai 	struct snd_timer_instance	*timeri;	/* timer instance */
341da177e4SLinus Torvalds 	unsigned int		ticks;
351da177e4SLinus Torvalds 	unsigned long		preferred_resolution; /* timer resolution, ticks/sec */
361da177e4SLinus Torvalds 
371da177e4SLinus Torvalds 	unsigned int skew;
381da177e4SLinus Torvalds 	unsigned int skew_base;
391da177e4SLinus Torvalds 
403915bf29SArnd Bergmann 	struct timespec64	last_update;	 /* time of last clock update, used for interpolation */
411da177e4SLinus Torvalds 
421da177e4SLinus Torvalds 	spinlock_t lock;
43c7e0b5bfSTakashi Iwai };
441da177e4SLinus Torvalds 
451da177e4SLinus Torvalds 
461da177e4SLinus Torvalds /* create new timer (constructor) */
47c7e0b5bfSTakashi Iwai struct snd_seq_timer *snd_seq_timer_new(void);
481da177e4SLinus Torvalds 
491da177e4SLinus Torvalds /* delete timer (destructor) */
50c7e0b5bfSTakashi Iwai void snd_seq_timer_delete(struct snd_seq_timer **tmr);
511da177e4SLinus Torvalds 
521da177e4SLinus Torvalds /* */
snd_seq_timer_update_tick(struct snd_seq_timer_tick * tick,unsigned long resolution)53c7e0b5bfSTakashi Iwai static inline void snd_seq_timer_update_tick(struct snd_seq_timer_tick *tick,
54c7e0b5bfSTakashi Iwai 					     unsigned long resolution)
551da177e4SLinus Torvalds {
561da177e4SLinus Torvalds 	if (tick->resolution > 0) {
571da177e4SLinus Torvalds 		tick->fraction += resolution;
581da177e4SLinus Torvalds 		tick->cur_tick += (unsigned int)(tick->fraction / tick->resolution);
591da177e4SLinus Torvalds 		tick->fraction %= tick->resolution;
601da177e4SLinus Torvalds 	}
611da177e4SLinus Torvalds }
621da177e4SLinus Torvalds 
631da177e4SLinus Torvalds 
641da177e4SLinus Torvalds /* compare timestamp between events */
651da177e4SLinus Torvalds /* return 1 if a >= b; otherwise return 0 */
snd_seq_compare_tick_time(snd_seq_tick_time_t * a,snd_seq_tick_time_t * b)661da177e4SLinus Torvalds static inline int snd_seq_compare_tick_time(snd_seq_tick_time_t *a, snd_seq_tick_time_t *b)
671da177e4SLinus Torvalds {
681da177e4SLinus Torvalds 	/* compare ticks */
691da177e4SLinus Torvalds 	return (*a >= *b);
701da177e4SLinus Torvalds }
711da177e4SLinus Torvalds 
snd_seq_compare_real_time(snd_seq_real_time_t * a,snd_seq_real_time_t * b)721da177e4SLinus Torvalds static inline int snd_seq_compare_real_time(snd_seq_real_time_t *a, snd_seq_real_time_t *b)
731da177e4SLinus Torvalds {
741da177e4SLinus Torvalds 	/* compare real time */
751da177e4SLinus Torvalds 	if (a->tv_sec > b->tv_sec)
761da177e4SLinus Torvalds 		return 1;
771da177e4SLinus Torvalds 	if ((a->tv_sec == b->tv_sec) && (a->tv_nsec >= b->tv_nsec))
781da177e4SLinus Torvalds 		return 1;
791da177e4SLinus Torvalds 	return 0;
801da177e4SLinus Torvalds }
811da177e4SLinus Torvalds 
821da177e4SLinus Torvalds 
snd_seq_sanity_real_time(snd_seq_real_time_t * tm)831da177e4SLinus Torvalds static inline void snd_seq_sanity_real_time(snd_seq_real_time_t *tm)
841da177e4SLinus Torvalds {
851da177e4SLinus Torvalds 	while (tm->tv_nsec >= 1000000000) {
861da177e4SLinus Torvalds 		/* roll-over */
871da177e4SLinus Torvalds 		tm->tv_nsec -= 1000000000;
881da177e4SLinus Torvalds                 tm->tv_sec++;
891da177e4SLinus Torvalds         }
901da177e4SLinus Torvalds }
911da177e4SLinus Torvalds 
921da177e4SLinus Torvalds 
931da177e4SLinus Torvalds /* increment timestamp */
snd_seq_inc_real_time(snd_seq_real_time_t * tm,snd_seq_real_time_t * inc)941da177e4SLinus Torvalds static inline void snd_seq_inc_real_time(snd_seq_real_time_t *tm, snd_seq_real_time_t *inc)
951da177e4SLinus Torvalds {
961da177e4SLinus Torvalds 	tm->tv_sec  += inc->tv_sec;
971da177e4SLinus Torvalds 	tm->tv_nsec += inc->tv_nsec;
981da177e4SLinus Torvalds 	snd_seq_sanity_real_time(tm);
991da177e4SLinus Torvalds }
1001da177e4SLinus Torvalds 
snd_seq_inc_time_nsec(snd_seq_real_time_t * tm,unsigned long nsec)1011da177e4SLinus Torvalds static inline void snd_seq_inc_time_nsec(snd_seq_real_time_t *tm, unsigned long nsec)
1021da177e4SLinus Torvalds {
1031da177e4SLinus Torvalds 	tm->tv_nsec  += nsec;
1041da177e4SLinus Torvalds 	snd_seq_sanity_real_time(tm);
1051da177e4SLinus Torvalds }
1061da177e4SLinus Torvalds 
1071da177e4SLinus Torvalds /* called by timer isr */
108c7e0b5bfSTakashi Iwai struct snd_seq_queue;
109c7e0b5bfSTakashi Iwai int snd_seq_timer_open(struct snd_seq_queue *q);
110c7e0b5bfSTakashi Iwai int snd_seq_timer_close(struct snd_seq_queue *q);
111c7e0b5bfSTakashi Iwai int snd_seq_timer_midi_open(struct snd_seq_queue *q);
112c7e0b5bfSTakashi Iwai int snd_seq_timer_midi_close(struct snd_seq_queue *q);
113c7e0b5bfSTakashi Iwai void snd_seq_timer_defaults(struct snd_seq_timer *tmr);
114c7e0b5bfSTakashi Iwai void snd_seq_timer_reset(struct snd_seq_timer *tmr);
115c7e0b5bfSTakashi Iwai int snd_seq_timer_stop(struct snd_seq_timer *tmr);
116c7e0b5bfSTakashi Iwai int snd_seq_timer_start(struct snd_seq_timer *tmr);
117c7e0b5bfSTakashi Iwai int snd_seq_timer_continue(struct snd_seq_timer *tmr);
118c7e0b5bfSTakashi Iwai int snd_seq_timer_set_tempo(struct snd_seq_timer *tmr, int tempo);
119671ec859STakashi Iwai int snd_seq_timer_set_tempo_ppq(struct snd_seq_timer *tmr, int tempo, int ppq);
120c7e0b5bfSTakashi Iwai int snd_seq_timer_set_position_tick(struct snd_seq_timer *tmr, snd_seq_tick_time_t position);
121c7e0b5bfSTakashi Iwai int snd_seq_timer_set_position_time(struct snd_seq_timer *tmr, snd_seq_real_time_t position);
122c7e0b5bfSTakashi Iwai int snd_seq_timer_set_skew(struct snd_seq_timer *tmr, unsigned int skew, unsigned int base);
123*dc749779STakashi Iwai snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr,
124*dc749779STakashi Iwai 					       bool adjust_ktime);
125c7e0b5bfSTakashi Iwai snd_seq_tick_time_t snd_seq_timer_get_cur_tick(struct snd_seq_timer *tmr);
1261da177e4SLinus Torvalds 
1273b378e1fSMarcin Ślusarz extern int seq_default_timer_class;
1283b378e1fSMarcin Ślusarz extern int seq_default_timer_sclass;
1293b378e1fSMarcin Ślusarz extern int seq_default_timer_card;
1303b378e1fSMarcin Ślusarz extern int seq_default_timer_device;
1313b378e1fSMarcin Ślusarz extern int seq_default_timer_subdevice;
1323b378e1fSMarcin Ślusarz extern int seq_default_timer_resolution;
1333b378e1fSMarcin Ślusarz 
1341da177e4SLinus Torvalds #endif
135