pcm: dmix: fix sw_params handling of timestamp types in direct plugins

In pcms using direct plugins (dmix/dsnoop/dshare), the timestamp type could
be different from the terminating hw plugin, then the kernel driver.

Be sure such pcms have plugins using consistently the same timestamp type.

signed-off-by: Sylvain Bertrand <sylvain.bertrand@legeek.net>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
sylvain.bertrand@gmail.com 2020-04-15 00:44:39 +00:00 committed by Takashi Iwai
parent fb48ad9e4f
commit d12df1dc9c
9 changed files with 60 additions and 1 deletions

View file

@ -69,6 +69,7 @@ defaults.pcm.minperiodtime 5000 # in us
defaults.pcm.ipc_key 5678293 defaults.pcm.ipc_key 5678293
defaults.pcm.ipc_gid audio defaults.pcm.ipc_gid audio
defaults.pcm.ipc_perm 0660 defaults.pcm.ipc_perm 0660
defaults.pcm.tstamp_type "default"
defaults.pcm.dmix.max_periods 0 defaults.pcm.dmix.max_periods 0
defaults.pcm.dmix.channels 2 defaults.pcm.dmix.channels 2
defaults.pcm.dmix.rate 48000 defaults.pcm.dmix.rate 48000

View file

@ -56,6 +56,10 @@ pcm.!dmix {
@func refer @func refer
name defaults.pcm.ipc_perm name defaults.pcm.ipc_perm
} }
tstamp_type {
@func refer
name defaults.pcm.tstamp_type
}
slave { slave {
pcm { pcm {
type hw type hw

View file

@ -49,6 +49,10 @@ pcm.!dsnoop {
@func refer @func refer
name defaults.pcm.ipc_perm name defaults.pcm.ipc_perm
} }
tstamp_type {
@func refer
name defaults.pcm.tstamp_type
}
slave { slave {
pcm { pcm {
type hw type hw

View file

@ -991,8 +991,11 @@ int snd_pcm_direct_hw_free(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
return 0; return 0;
} }
int snd_pcm_direct_sw_params(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t * params ATTRIBUTE_UNUSED) int snd_pcm_direct_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
{ {
if (params->tstamp_type != pcm->tstamp_type)
return -EINVAL;
/* values are cached in the pcm structure */ /* values are cached in the pcm structure */
return 0; return 0;
} }
@ -1318,6 +1321,15 @@ int snd_pcm_direct_initialize_slave(snd_pcm_direct_t *dmix, snd_pcm_t *spcm, str
return ret; return ret;
} }
if (dmix->tstamp_type != -1) {
ret = snd_pcm_sw_params_set_tstamp_type(spcm, &sw_params,
dmix->tstamp_type);
if (ret < 0) {
SNDERR("unable to set tstamp type");
return ret;
}
}
if (dmix->type != SND_PCM_TYPE_DMIX && if (dmix->type != SND_PCM_TYPE_DMIX &&
dmix->type != SND_PCM_TYPE_DSHARE) dmix->type != SND_PCM_TYPE_DSHARE)
goto __skip_silencing; goto __skip_silencing;
@ -1878,6 +1890,7 @@ int snd_pcm_direct_parse_open_conf(snd_config_t *root, snd_config_t *conf,
rec->var_periodsize = 0; rec->var_periodsize = 0;
rec->direct_memory_access = 1; rec->direct_memory_access = 1;
rec->hw_ptr_alignment = SND_PCM_HW_PTR_ALIGNMENT_AUTO; rec->hw_ptr_alignment = SND_PCM_HW_PTR_ALIGNMENT_AUTO;
rec->tstamp_type = -1;
/* read defaults */ /* read defaults */
if (snd_config_search(root, "defaults.pcm.dmix_max_periods", &n) >= 0) { if (snd_config_search(root, "defaults.pcm.dmix_max_periods", &n) >= 0) {
@ -1941,6 +1954,27 @@ int snd_pcm_direct_parse_open_conf(snd_config_t *root, snd_config_t *conf,
continue; continue;
} }
if (strcmp(id, "tstamp_type") == 0) {
const char *str;
err = snd_config_get_string(n, &str);
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
if (strcmp(str, "default") == 0)
rec->tstamp_type = -1;
else if (strcmp(str, "gettimeofday") == 0)
rec->tstamp_type = SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY;
else if (strcmp(str, "monotonic") == 0)
rec->tstamp_type = SND_PCM_TSTAMP_TYPE_MONOTONIC;
else if (strcmp(str, "monotonic_raw") == 0)
rec->tstamp_type = SND_PCM_TSTAMP_TYPE_MONOTONIC_RAW;
else {
SNDERR("The field tstamp_type is invalid : %s", str);
return -EINVAL;
}
continue;
}
if (strcmp(id, "ipc_gid") == 0) { if (strcmp(id, "ipc_gid") == 0) {
char *group; char *group;
char *endp; char *endp;

View file

@ -173,6 +173,7 @@ struct snd_pcm_direct {
unsigned int recoveries; /* mirror of executed recoveries on slave */ unsigned int recoveries; /* mirror of executed recoveries on slave */
int direct_memory_access; /* use arch-optimized buffer RW */ int direct_memory_access; /* use arch-optimized buffer RW */
snd_pcm_direct_hw_ptr_alignment_t hw_ptr_alignment; snd_pcm_direct_hw_ptr_alignment_t hw_ptr_alignment;
int tstamp_type; /* cached from conf, can be -1(default) on top of real types */
union { union {
struct { struct {
int shmid_sum; /* IPC global sum ring buffer memory identification */ int shmid_sum; /* IPC global sum ring buffer memory identification */
@ -357,6 +358,7 @@ struct snd_pcm_direct_open_conf {
int var_periodsize; int var_periodsize;
int direct_memory_access; int direct_memory_access;
snd_pcm_direct_hw_ptr_alignment_t hw_ptr_alignment; snd_pcm_direct_hw_ptr_alignment_t hw_ptr_alignment;
int tstamp_type;
snd_config_t *slave; snd_config_t *slave;
snd_config_t *bindings; snd_config_t *bindings;
}; };

View file

@ -1038,6 +1038,7 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
dmix->ipc_key = opts->ipc_key; dmix->ipc_key = opts->ipc_key;
dmix->ipc_perm = opts->ipc_perm; dmix->ipc_perm = opts->ipc_perm;
dmix->ipc_gid = opts->ipc_gid; dmix->ipc_gid = opts->ipc_gid;
dmix->tstamp_type = opts->tstamp_type;
dmix->semid = -1; dmix->semid = -1;
dmix->shmid = -1; dmix->shmid = -1;
@ -1237,6 +1238,9 @@ pcm.name {
# roundup # roundup
# rounddown # rounddown
# auto (default) # auto (default)
tstamp_type STR # timestamp type
# STR can be one of the below strings :
# default, gettimeofday, monotonic, monotonic_raw
slave STR slave STR
# or # or
slave { # Slave definition slave { # Slave definition

View file

@ -723,6 +723,7 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name,
dshare->ipc_key = opts->ipc_key; dshare->ipc_key = opts->ipc_key;
dshare->ipc_perm = opts->ipc_perm; dshare->ipc_perm = opts->ipc_perm;
dshare->ipc_gid = opts->ipc_gid; dshare->ipc_gid = opts->ipc_gid;
dshare->tstamp_type = opts->tstamp_type;
dshare->semid = -1; dshare->semid = -1;
dshare->shmid = -1; dshare->shmid = -1;
@ -929,6 +930,9 @@ pcm.name {
# roundup # roundup
# rounddown # rounddown
# auto (default) # auto (default)
tstamp_type STR # timestamp type
# STR can be one of the below strings :
# default, gettimeofday, monotonic, monotonic_raw
slave STR slave STR
# or # or
slave { # Slave definition slave { # Slave definition

View file

@ -591,6 +591,7 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name,
dsnoop->ipc_key = opts->ipc_key; dsnoop->ipc_key = opts->ipc_key;
dsnoop->ipc_perm = opts->ipc_perm; dsnoop->ipc_perm = opts->ipc_perm;
dsnoop->ipc_gid = opts->ipc_gid; dsnoop->ipc_gid = opts->ipc_gid;
dsnoop->tstamp_type = opts->tstamp_type;
dsnoop->semid = -1; dsnoop->semid = -1;
dsnoop->shmid = -1; dsnoop->shmid = -1;
@ -780,6 +781,9 @@ pcm.name {
# roundup # roundup
# rounddown # rounddown
# auto (default) # auto (default)
tstamp_type STR # timestamp type
# STR can be one of the below strings :
# default, gettimeofday, monotonic, monotonic_raw
slave STR slave STR
# or # or
slave { # Slave definition slave { # Slave definition

View file

@ -928,6 +928,8 @@ int INTERNAL(snd_pcm_hw_params_set_buffer_size_last)(snd_pcm_t *pcm, snd_pcm_hw_
int snd_pcm_sw_params_set_tstamp_mode(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_tstamp_t val); int snd_pcm_sw_params_set_tstamp_mode(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_tstamp_t val);
int INTERNAL(snd_pcm_sw_params_get_tstamp_mode)(const snd_pcm_sw_params_t *params, snd_pcm_tstamp_t *val); int INTERNAL(snd_pcm_sw_params_get_tstamp_mode)(const snd_pcm_sw_params_t *params, snd_pcm_tstamp_t *val);
int snd_pcm_sw_params_set_tstamp_type(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_tstamp_type_t val);
int snd_pcm_sw_params_get_tstamp_type(const snd_pcm_sw_params_t *params, snd_pcm_tstamp_type_t *val);
int snd_pcm_sw_params_set_avail_min(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val); int snd_pcm_sw_params_set_avail_min(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val);
int INTERNAL(snd_pcm_sw_params_get_avail_min)(const snd_pcm_sw_params_t *params, snd_pcm_uframes_t *val); int INTERNAL(snd_pcm_sw_params_get_avail_min)(const snd_pcm_sw_params_t *params, snd_pcm_uframes_t *val);
int snd_pcm_sw_params_set_start_threshold(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val); int snd_pcm_sw_params_set_start_threshold(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val);