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