Commit 229d0430 authored by Pierre-Louis Bossart's avatar Pierre-Louis Bossart Committed by Takashi Iwai

ALSA: core: selection of audio_tstamp type and accuracy reports

Audio timestamps can be extracted from sample counters, wall clocks,
PHC clocks (Ethernet AVB), on-demand synchronized snapshots. This
patch provides the ability to report timestamping capabilities, select
timestamp types and retrieve timestamp accuracy, if supported.
Details can be found in Documentations/sound/alsa/timestamping.txt

This functionality is introduced by reclaiming the reserved_aligned
field introduced by commit9c7066ae
in snd_pcm_status to provide userspace with selection/query capabilities.
Additional driver_tstamp and audio_tstamp_accuracy fields are also added.

snd_pcm_mmap_status remains a read-only structure with only
the audio timestamp value accessible from user space. The selection
of audio timestamp type is done through snd_pcm_status only

This commit does not impact ABI and does not impact the default
behavior. By default audio timestamp is aligned with hw_pointer and
reports the DMA position. Backwards compatibility is handled by using
the HDAudio wall clock for playback and the hw_ptr for all other
cases.

For timestamp selection a new STATUS_EXT ioctl is introduced with
read/write parameters. Alsa-lib will be modified to make use of
STATUS_EXT.
Signed-off-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 0c8d9485
This diff is collapsed.
...@@ -60,6 +60,9 @@ struct snd_pcm_hardware { ...@@ -60,6 +60,9 @@ struct snd_pcm_hardware {
struct snd_pcm_substream; struct snd_pcm_substream;
struct snd_pcm_audio_tstamp_config; /* definitions further down */
struct snd_pcm_audio_tstamp_report;
struct snd_pcm_ops { struct snd_pcm_ops {
int (*open)(struct snd_pcm_substream *substream); int (*open)(struct snd_pcm_substream *substream);
int (*close)(struct snd_pcm_substream *substream); int (*close)(struct snd_pcm_substream *substream);
...@@ -281,6 +284,58 @@ struct snd_pcm_hw_constraint_ranges { ...@@ -281,6 +284,58 @@ struct snd_pcm_hw_constraint_ranges {
struct snd_pcm_hwptr_log; struct snd_pcm_hwptr_log;
/*
* userspace-provided audio timestamp config to kernel,
* structure is for internal use only and filled with dedicated unpack routine
*/
struct snd_pcm_audio_tstamp_config {
/* 5 of max 16 bits used */
u32 type_requested:4;
u32 report_delay:1; /* add total delay to A/D or D/A */
};
static inline void snd_pcm_unpack_audio_tstamp_config(__u32 data,
struct snd_pcm_audio_tstamp_config *config)
{
config->type_requested = data & 0xF;
config->report_delay = (data >> 4) & 1;
}
/*
* kernel-provided audio timestamp report to user-space
* structure is for internal use only and read by dedicated pack routine
*/
struct snd_pcm_audio_tstamp_report {
/* 6 of max 16 bits used for bit-fields */
/* for backwards compatibility */
u32 valid:1;
/* actual type if hardware could not support requested timestamp */
u32 actual_type:4;
/* accuracy represented in ns units */
u32 accuracy_report:1; /* 0 if accuracy unknown, 1 if accuracy field is valid */
u32 accuracy; /* up to 4.29s, will be packed in separate field */
};
static inline void snd_pcm_pack_audio_tstamp_report(__u32 *data, __u32 *accuracy,
const struct snd_pcm_audio_tstamp_report *report)
{
u32 tmp;
tmp = report->accuracy_report;
tmp <<= 4;
tmp |= report->actual_type;
tmp <<= 1;
tmp |= report->valid;
*data &= 0xffff; /* zero-clear MSBs */
*data |= (tmp << 16);
*accuracy = report->accuracy;
}
struct snd_pcm_runtime { struct snd_pcm_runtime {
/* -- Status -- */ /* -- Status -- */
struct snd_pcm_substream *trigger_master; struct snd_pcm_substream *trigger_master;
...@@ -361,6 +416,11 @@ struct snd_pcm_runtime { ...@@ -361,6 +416,11 @@ struct snd_pcm_runtime {
struct snd_dma_buffer *dma_buffer_p; /* allocated buffer */ struct snd_dma_buffer *dma_buffer_p; /* allocated buffer */
/* -- audio timestamp config -- */
struct snd_pcm_audio_tstamp_config audio_tstamp_config;
struct snd_pcm_audio_tstamp_report audio_tstamp_report;
struct timespec driver_tstamp;
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
/* -- OSS things -- */ /* -- OSS things -- */
struct snd_pcm_oss_runtime oss; struct snd_pcm_oss_runtime oss;
......
...@@ -267,10 +267,17 @@ typedef int __bitwise snd_pcm_subformat_t; ...@@ -267,10 +267,17 @@ typedef int __bitwise snd_pcm_subformat_t;
#define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000 /* playback and capture stream are somewhat correlated */ #define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000 /* playback and capture stream are somewhat correlated */
#define SNDRV_PCM_INFO_SYNC_START 0x00400000 /* pcm support some kind of sync go */ #define SNDRV_PCM_INFO_SYNC_START 0x00400000 /* pcm support some kind of sync go */
#define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP 0x00800000 /* period wakeup can be disabled */ #define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP 0x00800000 /* period wakeup can be disabled */
#define SNDRV_PCM_INFO_HAS_WALL_CLOCK 0x01000000 /* has audio wall clock for audio/system time sync */ #define SNDRV_PCM_INFO_HAS_WALL_CLOCK 0x01000000 /* (Deprecated)has audio wall clock for audio/system time sync */
#define SNDRV_PCM_INFO_HAS_LINK_ATIME 0x01000000 /* report hardware link audio time, reset on startup */
#define SNDRV_PCM_INFO_HAS_LINK_ABSOLUTE_ATIME 0x02000000 /* report absolute hardware link audio time, not reset on startup */
#define SNDRV_PCM_INFO_HAS_LINK_ESTIMATED_ATIME 0x04000000 /* report estimated link audio time */
#define SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME 0x08000000 /* report synchronized audio/system time */
#define SNDRV_PCM_INFO_DRAIN_TRIGGER 0x40000000 /* internal kernel flag - trigger in drain */ #define SNDRV_PCM_INFO_DRAIN_TRIGGER 0x40000000 /* internal kernel flag - trigger in drain */
#define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000 /* internal kernel flag - FIFO size is in frames */ #define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000 /* internal kernel flag - FIFO size is in frames */
typedef int __bitwise snd_pcm_state_t; typedef int __bitwise snd_pcm_state_t;
#define SNDRV_PCM_STATE_OPEN ((__force snd_pcm_state_t) 0) /* stream is open */ #define SNDRV_PCM_STATE_OPEN ((__force snd_pcm_state_t) 0) /* stream is open */
#define SNDRV_PCM_STATE_SETUP ((__force snd_pcm_state_t) 1) /* stream has a setup */ #define SNDRV_PCM_STATE_SETUP ((__force snd_pcm_state_t) 1) /* stream has a setup */
...@@ -408,6 +415,22 @@ struct snd_pcm_channel_info { ...@@ -408,6 +415,22 @@ struct snd_pcm_channel_info {
unsigned int step; /* samples distance in bits */ unsigned int step; /* samples distance in bits */
}; };
enum {
/*
* first definition for backwards compatibility only,
* maps to wallclock/link time for HDAudio playback and DEFAULT/DMA time for everything else
*/
SNDRV_PCM_AUDIO_TSTAMP_TYPE_COMPAT = 0,
/* timestamp definitions */
SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT = 1, /* DMA time, reported as per hw_ptr */
SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK = 2, /* link time reported by sample or wallclock counter, reset on startup */
SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_ABSOLUTE = 3, /* link time reported by sample or wallclock counter, not reset on startup */
SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_ESTIMATED = 4, /* link time estimated indirectly */
SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED = 5, /* link time synchronized with system time */
SNDRV_PCM_AUDIO_TSTAMP_TYPE_LAST = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED
};
struct snd_pcm_status { struct snd_pcm_status {
snd_pcm_state_t state; /* stream state */ snd_pcm_state_t state; /* stream state */
struct timespec trigger_tstamp; /* time when stream was started/stopped/paused */ struct timespec trigger_tstamp; /* time when stream was started/stopped/paused */
...@@ -419,9 +442,11 @@ struct snd_pcm_status { ...@@ -419,9 +442,11 @@ struct snd_pcm_status {
snd_pcm_uframes_t avail_max; /* max frames available on hw since last status */ snd_pcm_uframes_t avail_max; /* max frames available on hw since last status */
snd_pcm_uframes_t overrange; /* count of ADC (capture) overrange detections from last status */ snd_pcm_uframes_t overrange; /* count of ADC (capture) overrange detections from last status */
snd_pcm_state_t suspended_state; /* suspended stream state */ snd_pcm_state_t suspended_state; /* suspended stream state */
__u32 reserved_alignment; /* must be filled with zero */ __u32 audio_tstamp_data; /* needed for 64-bit alignment, used for configs/report to/from userspace */
struct timespec audio_tstamp; /* from sample counter or wall clock */ struct timespec audio_tstamp; /* sample counter, wall clock, PHC or on-demand sync'ed */
unsigned char reserved[56-sizeof(struct timespec)]; /* must be filled with zero */ struct timespec driver_tstamp; /* useful in case reference system tstamp is reported with delay */
__u32 audio_tstamp_accuracy; /* in ns units, only valid if indicated in audio_tstamp_data */
unsigned char reserved[52-2*sizeof(struct timespec)]; /* must be filled with zero */
}; };
struct snd_pcm_mmap_status { struct snd_pcm_mmap_status {
...@@ -534,6 +559,7 @@ enum { ...@@ -534,6 +559,7 @@ enum {
#define SNDRV_PCM_IOCTL_DELAY _IOR('A', 0x21, snd_pcm_sframes_t) #define SNDRV_PCM_IOCTL_DELAY _IOR('A', 0x21, snd_pcm_sframes_t)
#define SNDRV_PCM_IOCTL_HWSYNC _IO('A', 0x22) #define SNDRV_PCM_IOCTL_HWSYNC _IO('A', 0x22)
#define SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct snd_pcm_sync_ptr) #define SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct snd_pcm_sync_ptr)
#define SNDRV_PCM_IOCTL_STATUS_EXT _IOWR('A', 0x24, struct snd_pcm_status)
#define SNDRV_PCM_IOCTL_CHANNEL_INFO _IOR('A', 0x32, struct snd_pcm_channel_info) #define SNDRV_PCM_IOCTL_CHANNEL_INFO _IOR('A', 0x32, struct snd_pcm_channel_info)
#define SNDRV_PCM_IOCTL_PREPARE _IO('A', 0x40) #define SNDRV_PCM_IOCTL_PREPARE _IO('A', 0x40)
#define SNDRV_PCM_IOCTL_RESET _IO('A', 0x41) #define SNDRV_PCM_IOCTL_RESET _IO('A', 0x41)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment