18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 28c2ecf20Sopenharmony_ci#ifndef __SOUND_TIMER_H 38c2ecf20Sopenharmony_ci#define __SOUND_TIMER_H 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci/* 68c2ecf20Sopenharmony_ci * Timer abstract layer 78c2ecf20Sopenharmony_ci * Copyright (c) by Jaroslav Kysela <perex@perex.cz>, 88c2ecf20Sopenharmony_ci * Abramo Bagnara <abramo@alsa-project.org> 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <sound/asound.h> 128c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#define snd_timer_chip(timer) ((timer)->private_data) 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#define SNDRV_TIMER_DEVICES 16 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define SNDRV_TIMER_DEV_FLG_PCM 0x10000000 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#define SNDRV_TIMER_HW_AUTO 0x00000001 /* auto trigger is supported */ 218c2ecf20Sopenharmony_ci#define SNDRV_TIMER_HW_STOP 0x00000002 /* call stop before start */ 228c2ecf20Sopenharmony_ci#define SNDRV_TIMER_HW_SLAVE 0x00000004 /* only slave timer (variable resolution) */ 238c2ecf20Sopenharmony_ci#define SNDRV_TIMER_HW_FIRST 0x00000008 /* first tick can be incomplete */ 248c2ecf20Sopenharmony_ci#define SNDRV_TIMER_HW_WORK 0x00000010 /* timer is called from work */ 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#define SNDRV_TIMER_IFLG_SLAVE 0x00000001 278c2ecf20Sopenharmony_ci#define SNDRV_TIMER_IFLG_RUNNING 0x00000002 288c2ecf20Sopenharmony_ci#define SNDRV_TIMER_IFLG_START 0x00000004 298c2ecf20Sopenharmony_ci#define SNDRV_TIMER_IFLG_AUTO 0x00000008 /* auto restart */ 308c2ecf20Sopenharmony_ci#define SNDRV_TIMER_IFLG_FAST 0x00000010 /* fast callback (do not use work) */ 318c2ecf20Sopenharmony_ci#define SNDRV_TIMER_IFLG_CALLBACK 0x00000020 /* timer callback is active */ 328c2ecf20Sopenharmony_ci#define SNDRV_TIMER_IFLG_EXCLUSIVE 0x00000040 /* exclusive owner - no more instances */ 338c2ecf20Sopenharmony_ci#define SNDRV_TIMER_IFLG_EARLY_EVENT 0x00000080 /* write early event to the poll queue */ 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#define SNDRV_TIMER_FLG_CHANGE 0x00000001 368c2ecf20Sopenharmony_ci#define SNDRV_TIMER_FLG_RESCHED 0x00000002 /* need reschedule */ 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistruct snd_timer; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cistruct snd_timer_hardware { 418c2ecf20Sopenharmony_ci /* -- must be filled with low-level driver */ 428c2ecf20Sopenharmony_ci unsigned int flags; /* various flags */ 438c2ecf20Sopenharmony_ci unsigned long resolution; /* average timer resolution for one tick in nsec */ 448c2ecf20Sopenharmony_ci unsigned long resolution_min; /* minimal resolution */ 458c2ecf20Sopenharmony_ci unsigned long resolution_max; /* maximal resolution */ 468c2ecf20Sopenharmony_ci unsigned long ticks; /* max timer ticks per interrupt */ 478c2ecf20Sopenharmony_ci /* -- low-level functions -- */ 488c2ecf20Sopenharmony_ci int (*open) (struct snd_timer * timer); 498c2ecf20Sopenharmony_ci int (*close) (struct snd_timer * timer); 508c2ecf20Sopenharmony_ci unsigned long (*c_resolution) (struct snd_timer * timer); 518c2ecf20Sopenharmony_ci int (*start) (struct snd_timer * timer); 528c2ecf20Sopenharmony_ci int (*stop) (struct snd_timer * timer); 538c2ecf20Sopenharmony_ci int (*set_period) (struct snd_timer * timer, unsigned long period_num, unsigned long period_den); 548c2ecf20Sopenharmony_ci int (*precise_resolution) (struct snd_timer * timer, unsigned long *num, unsigned long *den); 558c2ecf20Sopenharmony_ci}; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cistruct snd_timer { 588c2ecf20Sopenharmony_ci int tmr_class; 598c2ecf20Sopenharmony_ci struct snd_card *card; 608c2ecf20Sopenharmony_ci struct module *module; 618c2ecf20Sopenharmony_ci int tmr_device; 628c2ecf20Sopenharmony_ci int tmr_subdevice; 638c2ecf20Sopenharmony_ci char id[64]; 648c2ecf20Sopenharmony_ci char name[80]; 658c2ecf20Sopenharmony_ci unsigned int flags; 668c2ecf20Sopenharmony_ci int running; /* running instances */ 678c2ecf20Sopenharmony_ci unsigned long sticks; /* schedule ticks */ 688c2ecf20Sopenharmony_ci void *private_data; 698c2ecf20Sopenharmony_ci void (*private_free) (struct snd_timer *timer); 708c2ecf20Sopenharmony_ci struct snd_timer_hardware hw; 718c2ecf20Sopenharmony_ci spinlock_t lock; 728c2ecf20Sopenharmony_ci struct list_head device_list; 738c2ecf20Sopenharmony_ci struct list_head open_list_head; 748c2ecf20Sopenharmony_ci struct list_head active_list_head; 758c2ecf20Sopenharmony_ci struct list_head ack_list_head; 768c2ecf20Sopenharmony_ci struct list_head sack_list_head; /* slow ack list head */ 778c2ecf20Sopenharmony_ci struct work_struct task_work; 788c2ecf20Sopenharmony_ci int max_instances; /* upper limit of timer instances */ 798c2ecf20Sopenharmony_ci int num_instances; /* current number of timer instances */ 808c2ecf20Sopenharmony_ci}; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cistruct snd_timer_instance { 838c2ecf20Sopenharmony_ci struct snd_timer *timer; 848c2ecf20Sopenharmony_ci char *owner; 858c2ecf20Sopenharmony_ci unsigned int flags; 868c2ecf20Sopenharmony_ci void *private_data; 878c2ecf20Sopenharmony_ci void (*private_free) (struct snd_timer_instance *ti); 888c2ecf20Sopenharmony_ci void (*callback) (struct snd_timer_instance *timeri, 898c2ecf20Sopenharmony_ci unsigned long ticks, unsigned long resolution); 908c2ecf20Sopenharmony_ci void (*ccallback) (struct snd_timer_instance * timeri, 918c2ecf20Sopenharmony_ci int event, 928c2ecf20Sopenharmony_ci struct timespec64 * tstamp, 938c2ecf20Sopenharmony_ci unsigned long resolution); 948c2ecf20Sopenharmony_ci void (*disconnect)(struct snd_timer_instance *timeri); 958c2ecf20Sopenharmony_ci void *callback_data; 968c2ecf20Sopenharmony_ci unsigned long ticks; /* auto-load ticks when expired */ 978c2ecf20Sopenharmony_ci unsigned long cticks; /* current ticks */ 988c2ecf20Sopenharmony_ci unsigned long pticks; /* accumulated ticks for callback */ 998c2ecf20Sopenharmony_ci unsigned long resolution; /* current resolution for work */ 1008c2ecf20Sopenharmony_ci unsigned long lost; /* lost ticks */ 1018c2ecf20Sopenharmony_ci int slave_class; 1028c2ecf20Sopenharmony_ci unsigned int slave_id; 1038c2ecf20Sopenharmony_ci struct list_head open_list; 1048c2ecf20Sopenharmony_ci struct list_head active_list; 1058c2ecf20Sopenharmony_ci struct list_head ack_list; 1068c2ecf20Sopenharmony_ci struct list_head slave_list_head; 1078c2ecf20Sopenharmony_ci struct list_head slave_active_head; 1088c2ecf20Sopenharmony_ci struct snd_timer_instance *master; 1098c2ecf20Sopenharmony_ci}; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci/* 1128c2ecf20Sopenharmony_ci * Registering 1138c2ecf20Sopenharmony_ci */ 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ciint snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, struct snd_timer **rtimer); 1168c2ecf20Sopenharmony_civoid snd_timer_notify(struct snd_timer *timer, int event, struct timespec64 *tstamp); 1178c2ecf20Sopenharmony_ciint snd_timer_global_new(char *id, int device, struct snd_timer **rtimer); 1188c2ecf20Sopenharmony_ciint snd_timer_global_free(struct snd_timer *timer); 1198c2ecf20Sopenharmony_ciint snd_timer_global_register(struct snd_timer *timer); 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_cistruct snd_timer_instance *snd_timer_instance_new(const char *owner); 1228c2ecf20Sopenharmony_civoid snd_timer_instance_free(struct snd_timer_instance *timeri); 1238c2ecf20Sopenharmony_ciint snd_timer_open(struct snd_timer_instance *timeri, struct snd_timer_id *tid, unsigned int slave_id); 1248c2ecf20Sopenharmony_civoid snd_timer_close(struct snd_timer_instance *timeri); 1258c2ecf20Sopenharmony_ciunsigned long snd_timer_resolution(struct snd_timer_instance *timeri); 1268c2ecf20Sopenharmony_ciint snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks); 1278c2ecf20Sopenharmony_ciint snd_timer_stop(struct snd_timer_instance *timeri); 1288c2ecf20Sopenharmony_ciint snd_timer_continue(struct snd_timer_instance *timeri); 1298c2ecf20Sopenharmony_ciint snd_timer_pause(struct snd_timer_instance *timeri); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_civoid snd_timer_interrupt(struct snd_timer *timer, unsigned long ticks_left); 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci#endif /* __SOUND_TIMER_H */ 134