162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
262306a36Sopenharmony_ci#ifndef __SOUND_TIMER_H
362306a36Sopenharmony_ci#define __SOUND_TIMER_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci/*
662306a36Sopenharmony_ci *  Timer abstract layer
762306a36Sopenharmony_ci *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
862306a36Sopenharmony_ci *		     Abramo Bagnara <abramo@alsa-project.org>
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <sound/asound.h>
1262306a36Sopenharmony_ci#include <linux/interrupt.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#define snd_timer_chip(timer) ((timer)->private_data)
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#define SNDRV_TIMER_DEVICES	16
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#define SNDRV_TIMER_DEV_FLG_PCM	0x10000000
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#define SNDRV_TIMER_HW_AUTO	0x00000001	/* auto trigger is supported */
2162306a36Sopenharmony_ci#define SNDRV_TIMER_HW_STOP	0x00000002	/* call stop before start */
2262306a36Sopenharmony_ci#define SNDRV_TIMER_HW_SLAVE	0x00000004	/* only slave timer (variable resolution) */
2362306a36Sopenharmony_ci#define SNDRV_TIMER_HW_FIRST	0x00000008	/* first tick can be incomplete */
2462306a36Sopenharmony_ci#define SNDRV_TIMER_HW_WORK	0x00000010	/* timer is called from work */
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#define SNDRV_TIMER_IFLG_SLAVE	  0x00000001
2762306a36Sopenharmony_ci#define SNDRV_TIMER_IFLG_RUNNING  0x00000002
2862306a36Sopenharmony_ci#define SNDRV_TIMER_IFLG_START	  0x00000004
2962306a36Sopenharmony_ci#define SNDRV_TIMER_IFLG_AUTO	  0x00000008	/* auto restart */
3062306a36Sopenharmony_ci#define SNDRV_TIMER_IFLG_FAST	  0x00000010	/* fast callback (do not use work) */
3162306a36Sopenharmony_ci#define SNDRV_TIMER_IFLG_CALLBACK 0x00000020	/* timer callback is active */
3262306a36Sopenharmony_ci#define SNDRV_TIMER_IFLG_EXCLUSIVE 0x00000040	/* exclusive owner - no more instances */
3362306a36Sopenharmony_ci#define SNDRV_TIMER_IFLG_EARLY_EVENT 0x00000080	/* write early event to the poll queue */
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci#define SNDRV_TIMER_FLG_CHANGE	0x00000001
3662306a36Sopenharmony_ci#define SNDRV_TIMER_FLG_RESCHED	0x00000002	/* need reschedule */
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cistruct snd_timer;
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_cistruct snd_timer_hardware {
4162306a36Sopenharmony_ci	/* -- must be filled with low-level driver */
4262306a36Sopenharmony_ci	unsigned int flags;		/* various flags */
4362306a36Sopenharmony_ci	unsigned long resolution;	/* average timer resolution for one tick in nsec */
4462306a36Sopenharmony_ci	unsigned long resolution_min;	/* minimal resolution */
4562306a36Sopenharmony_ci	unsigned long resolution_max;	/* maximal resolution */
4662306a36Sopenharmony_ci	unsigned long ticks;		/* max timer ticks per interrupt */
4762306a36Sopenharmony_ci	/* -- low-level functions -- */
4862306a36Sopenharmony_ci	int (*open) (struct snd_timer * timer);
4962306a36Sopenharmony_ci	int (*close) (struct snd_timer * timer);
5062306a36Sopenharmony_ci	unsigned long (*c_resolution) (struct snd_timer * timer);
5162306a36Sopenharmony_ci	int (*start) (struct snd_timer * timer);
5262306a36Sopenharmony_ci	int (*stop) (struct snd_timer * timer);
5362306a36Sopenharmony_ci	int (*set_period) (struct snd_timer * timer, unsigned long period_num, unsigned long period_den);
5462306a36Sopenharmony_ci	int (*precise_resolution) (struct snd_timer * timer, unsigned long *num, unsigned long *den);
5562306a36Sopenharmony_ci};
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_cistruct snd_timer {
5862306a36Sopenharmony_ci	int tmr_class;
5962306a36Sopenharmony_ci	struct snd_card *card;
6062306a36Sopenharmony_ci	struct module *module;
6162306a36Sopenharmony_ci	int tmr_device;
6262306a36Sopenharmony_ci	int tmr_subdevice;
6362306a36Sopenharmony_ci	char id[64];
6462306a36Sopenharmony_ci	char name[80];
6562306a36Sopenharmony_ci	unsigned int flags;
6662306a36Sopenharmony_ci	int running;			/* running instances */
6762306a36Sopenharmony_ci	unsigned long sticks;		/* schedule ticks */
6862306a36Sopenharmony_ci	void *private_data;
6962306a36Sopenharmony_ci	void (*private_free) (struct snd_timer *timer);
7062306a36Sopenharmony_ci	struct snd_timer_hardware hw;
7162306a36Sopenharmony_ci	spinlock_t lock;
7262306a36Sopenharmony_ci	struct list_head device_list;
7362306a36Sopenharmony_ci	struct list_head open_list_head;
7462306a36Sopenharmony_ci	struct list_head active_list_head;
7562306a36Sopenharmony_ci	struct list_head ack_list_head;
7662306a36Sopenharmony_ci	struct list_head sack_list_head; /* slow ack list head */
7762306a36Sopenharmony_ci	struct work_struct task_work;
7862306a36Sopenharmony_ci	int max_instances;	/* upper limit of timer instances */
7962306a36Sopenharmony_ci	int num_instances;	/* current number of timer instances */
8062306a36Sopenharmony_ci};
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cistruct snd_timer_instance {
8362306a36Sopenharmony_ci	struct snd_timer *timer;
8462306a36Sopenharmony_ci	char *owner;
8562306a36Sopenharmony_ci	unsigned int flags;
8662306a36Sopenharmony_ci	void *private_data;
8762306a36Sopenharmony_ci	void (*private_free) (struct snd_timer_instance *ti);
8862306a36Sopenharmony_ci	void (*callback) (struct snd_timer_instance *timeri,
8962306a36Sopenharmony_ci			  unsigned long ticks, unsigned long resolution);
9062306a36Sopenharmony_ci	void (*ccallback) (struct snd_timer_instance * timeri,
9162306a36Sopenharmony_ci			   int event,
9262306a36Sopenharmony_ci			   struct timespec64 * tstamp,
9362306a36Sopenharmony_ci			   unsigned long resolution);
9462306a36Sopenharmony_ci	void (*disconnect)(struct snd_timer_instance *timeri);
9562306a36Sopenharmony_ci	void *callback_data;
9662306a36Sopenharmony_ci	unsigned long ticks;		/* auto-load ticks when expired */
9762306a36Sopenharmony_ci	unsigned long cticks;		/* current ticks */
9862306a36Sopenharmony_ci	unsigned long pticks;		/* accumulated ticks for callback */
9962306a36Sopenharmony_ci	unsigned long resolution;	/* current resolution for work */
10062306a36Sopenharmony_ci	unsigned long lost;		/* lost ticks */
10162306a36Sopenharmony_ci	int slave_class;
10262306a36Sopenharmony_ci	unsigned int slave_id;
10362306a36Sopenharmony_ci	struct list_head open_list;
10462306a36Sopenharmony_ci	struct list_head active_list;
10562306a36Sopenharmony_ci	struct list_head ack_list;
10662306a36Sopenharmony_ci	struct list_head slave_list_head;
10762306a36Sopenharmony_ci	struct list_head slave_active_head;
10862306a36Sopenharmony_ci	struct snd_timer_instance *master;
10962306a36Sopenharmony_ci};
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci/*
11262306a36Sopenharmony_ci *  Registering
11362306a36Sopenharmony_ci */
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ciint snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, struct snd_timer **rtimer);
11662306a36Sopenharmony_civoid snd_timer_notify(struct snd_timer *timer, int event, struct timespec64 *tstamp);
11762306a36Sopenharmony_ciint snd_timer_global_new(char *id, int device, struct snd_timer **rtimer);
11862306a36Sopenharmony_ciint snd_timer_global_free(struct snd_timer *timer);
11962306a36Sopenharmony_ciint snd_timer_global_register(struct snd_timer *timer);
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_cistruct snd_timer_instance *snd_timer_instance_new(const char *owner);
12262306a36Sopenharmony_civoid snd_timer_instance_free(struct snd_timer_instance *timeri);
12362306a36Sopenharmony_ciint snd_timer_open(struct snd_timer_instance *timeri, struct snd_timer_id *tid, unsigned int slave_id);
12462306a36Sopenharmony_civoid snd_timer_close(struct snd_timer_instance *timeri);
12562306a36Sopenharmony_ciunsigned long snd_timer_resolution(struct snd_timer_instance *timeri);
12662306a36Sopenharmony_ciint snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks);
12762306a36Sopenharmony_ciint snd_timer_stop(struct snd_timer_instance *timeri);
12862306a36Sopenharmony_ciint snd_timer_continue(struct snd_timer_instance *timeri);
12962306a36Sopenharmony_ciint snd_timer_pause(struct snd_timer_instance *timeri);
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_civoid snd_timer_interrupt(struct snd_timer *timer, unsigned long ticks_left);
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci#endif /* __SOUND_TIMER_H */
134