- Backport upstream fix patches, including the deadlock fix for aplay/arecord (boo#1031525): 0001-ucm-Add-ATTRIBUTE_UNUSED-for-unused-parameters-of-ex.patch 0002-ucm-parser-needs-limits.h.patch 0003-pcm-direct-allow-users-to-configure-different-period.patch 0004-pcm-dshare-enable-silence.patch 0005-pcm-rate-fix-the-hw_ptr-update-until-the-boundary-av.patch 0006-plugin-dynamically-update-avail_min-on-slave.patch 0007-rate-dynamic-update-avail_min-on-slave.patch 0008-topology-fix-unused-const-variable-warning.patch 0009-seq-improve-documentation-about-new-get-pid-card-fun.patch 0010-pcm-direct-returning-semop-error-code-for-semaphore-.patch 0011-pcm-direct-Fix-for-sync-issue-on-xrun-recover.patch 0012-pcm-direct-check-state-before-enter-poll-on-timer.patch 0013-pcm-direct-don-t-return-bogus-buffer-levels-in-xrun-.patch 0014-conf-ucm-broxton-add-broxton-rt298-conf-files.patch 0015-pcm-direct-Fix-deadlock-in-poll_descriptors.patch 0016-ucm-Assure-the-user-input-card-name-not-to-exceed-ma.patch 0017-ucm-Load-device-specific-configuration-file-based-on.patch 0018-ucm-Add-command-get-_file-to-get-the-config-file-nam.patch 0019-topology-Fix-incorrect-license-in-source-comments.patch 0020-conf-cards-add-support-for-pistachio-card.patch 0021-pcm-multi-Drop-the-fixed-slave_map-in-snd_pcm_multi_.patch 0022-conf-Add-card-config-for-Intel-HDMI-DP-LPE-audio.patch 0023-pcm-Avoid-lock-for-snd_pcm_nonblock.patch 0024-pcm-Disable-locking-in-async-mode.patch 0025-pcm-dmix-Allow-disabling-x86-optimizations.patch 0026-pcm-dmix_rewind-corrupts-application-pointer-fix.patch 0027-pcm-direct-fix-race-on-clearing-timer-events.patch 0028-pcm-file-Enable-file-writing-for-capture-path.patch OBS-URL: https://build.opensuse.org/request/show/483406 OBS-URL: https://build.opensuse.org/package/show/multimedia:libs/alsa?expand=0&rev=210
238 lines
7.9 KiB
Diff
238 lines
7.9 KiB
Diff
From 0a61c796810fcec8b386e5311e871b1744b45a67 Mon Sep 17 00:00:00 2001
|
|
From: Joshua Frkuska <joshua_frkuska@mentor.com>
|
|
Date: Fri, 30 Dec 2016 11:56:15 +0530
|
|
Subject: [PATCH 03/43] pcm: direct: allow users to configure different period
|
|
sizes
|
|
|
|
This patch allows the effective period size to be a multiple of the
|
|
slave-pcm period size.
|
|
Allowing only exact multiple of original period size is achieved by
|
|
borrowing code from the kernel hwrules implementation.
|
|
|
|
This patch is intended to save cpu workload when for example, the
|
|
slave operates with very small periods but a user does not need that
|
|
small periods.
|
|
|
|
This feature is enabled by default and can be disabled by adding
|
|
config option 'var_periodsize 0'.
|
|
|
|
Signed-off-by: Alexander Jahn <ajahn@de.adit-jv.com>
|
|
Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
|
|
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
---
|
|
src/pcm/pcm_direct.c | 88 +++++++++++++++++++++++++++++++++++++++++++++------
|
|
src/pcm/pcm_direct.h | 3 +
|
|
src/pcm/pcm_dmix.c | 1
|
|
src/pcm/pcm_dshare.c | 1
|
|
src/pcm/pcm_dsnoop.c | 1
|
|
5 files changed, 84 insertions(+), 10 deletions(-)
|
|
|
|
--- a/src/pcm/pcm_direct.c
|
|
+++ b/src/pcm/pcm_direct.c
|
|
@@ -660,6 +660,29 @@ static int hw_param_interval_refine_minm
|
|
return hw_param_interval_refine_one(params, var, &t);
|
|
}
|
|
|
|
+/* this code is used 'as-is' from the alsa kernel code */
|
|
+static int snd_interval_step(struct snd_interval *i, unsigned int min,
|
|
+ unsigned int step)
|
|
+{
|
|
+ unsigned int n;
|
|
+ int changed = 0;
|
|
+ n = (i->min - min) % step;
|
|
+ if (n != 0 || i->openmin) {
|
|
+ i->min += step - n;
|
|
+ changed = 1;
|
|
+ }
|
|
+ n = (i->max - min) % step;
|
|
+ if (n != 0 || i->openmax) {
|
|
+ i->max -= n;
|
|
+ changed = 1;
|
|
+ }
|
|
+ if (snd_interval_checkempty(i)) {
|
|
+ i->empty = 1;
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ return changed;
|
|
+}
|
|
+
|
|
#undef REFINE_DEBUG
|
|
|
|
int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
|
@@ -710,15 +733,16 @@ int snd_pcm_direct_hw_refine(snd_pcm_t *
|
|
&dshare->shmptr->hw.rate);
|
|
if (err < 0)
|
|
return err;
|
|
- err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_SIZE,
|
|
- &dshare->shmptr->hw.period_size);
|
|
- if (err < 0)
|
|
- return err;
|
|
- err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_TIME,
|
|
- &dshare->shmptr->hw.period_time);
|
|
- if (err < 0)
|
|
- return err;
|
|
+
|
|
if (dshare->max_periods < 0) {
|
|
+ err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_SIZE,
|
|
+ &dshare->shmptr->hw.period_size);
|
|
+ if (err < 0)
|
|
+ return err;
|
|
+ err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_TIME,
|
|
+ &dshare->shmptr->hw.period_time);
|
|
+ if (err < 0)
|
|
+ return err;
|
|
err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_BUFFER_SIZE,
|
|
&dshare->shmptr->hw.buffer_size);
|
|
if (err < 0)
|
|
@@ -730,11 +754,38 @@ int snd_pcm_direct_hw_refine(snd_pcm_t *
|
|
} else if (params->rmask & ((1<<SND_PCM_HW_PARAM_PERIODS)|
|
|
(1<<SND_PCM_HW_PARAM_BUFFER_BYTES)|
|
|
(1<<SND_PCM_HW_PARAM_BUFFER_SIZE)|
|
|
- (1<<SND_PCM_HW_PARAM_BUFFER_TIME))) {
|
|
+ (1<<SND_PCM_HW_PARAM_BUFFER_TIME)|
|
|
+ (1<<SND_PCM_HW_PARAM_PERIOD_TIME)|
|
|
+ (1<<SND_PCM_HW_PARAM_PERIOD_SIZE)|
|
|
+ (1<<SND_PCM_HW_PARAM_PERIOD_BYTES))) {
|
|
+ snd_interval_t period_size = dshare->shmptr->hw.period_size;
|
|
+ snd_interval_t period_time = dshare->shmptr->hw.period_time;
|
|
int changed;
|
|
unsigned int max_periods = dshare->max_periods;
|
|
if (max_periods < 2)
|
|
max_periods = dshare->slave_buffer_size / dshare->slave_period_size;
|
|
+
|
|
+ /* make sure buffer size does not exceed slave buffer size */
|
|
+ err = hw_param_interval_refine_minmax(params, SND_PCM_HW_PARAM_BUFFER_SIZE,
|
|
+ 2 * dshare->slave_period_size, dshare->slave_buffer_size);
|
|
+ if (err < 0)
|
|
+ return err;
|
|
+ if (dshare->var_periodsize) {
|
|
+ /* more tolerant settings... */
|
|
+ if (dshare->shmptr->hw.buffer_size.max / 2 > period_size.max)
|
|
+ period_size.max = dshare->shmptr->hw.buffer_size.max / 2;
|
|
+ if (dshare->shmptr->hw.buffer_time.max / 2 > period_time.max)
|
|
+ period_time.max = dshare->shmptr->hw.buffer_time.max / 2;
|
|
+ }
|
|
+
|
|
+ err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_SIZE,
|
|
+ &period_size);
|
|
+ if (err < 0)
|
|
+ return err;
|
|
+ err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_TIME,
|
|
+ &period_time);
|
|
+ if (err < 0)
|
|
+ return err;
|
|
do {
|
|
changed = 0;
|
|
err = hw_param_interval_refine_minmax(params, SND_PCM_HW_PARAM_PERIODS,
|
|
@@ -746,8 +797,16 @@ int snd_pcm_direct_hw_refine(snd_pcm_t *
|
|
if (err < 0)
|
|
return err;
|
|
changed |= err;
|
|
+ err = snd_interval_step(hw_param_interval(params, SND_PCM_HW_PARAM_PERIOD_SIZE),
|
|
+ 0, dshare->slave_period_size);
|
|
+ if (err < 0)
|
|
+ return err;
|
|
+ changed |= err;
|
|
+ if (err)
|
|
+ params->rmask |= (1 << SND_PCM_HW_PARAM_PERIOD_SIZE);
|
|
} while (changed);
|
|
}
|
|
+ dshare->timer_ticks = hw_param_interval(params, SND_PCM_HW_PARAM_PERIOD_SIZE)->max / dshare->slave_period_size;
|
|
params->info = dshare->shmptr->s.info;
|
|
#ifdef REFINE_DEBUG
|
|
snd_output_puts(log, "DMIX REFINE (end):\n");
|
|
@@ -1183,6 +1242,7 @@ int snd_pcm_direct_initialize_poll_fd(sn
|
|
|
|
dmix->tread = 1;
|
|
dmix->timer_need_poll = 0;
|
|
+ dmix->timer_ticks = 1;
|
|
ret = snd_pcm_info(dmix->spcm, &info);
|
|
if (ret < 0) {
|
|
SNDERR("unable to info for slave pcm");
|
|
@@ -1366,7 +1426,7 @@ int snd_pcm_direct_set_timer_params(snd_
|
|
snd_timer_params_set_auto_start(¶ms, 1);
|
|
if (dmix->type != SND_PCM_TYPE_DSNOOP)
|
|
snd_timer_params_set_early_event(¶ms, 1);
|
|
- snd_timer_params_set_ticks(¶ms, 1);
|
|
+ snd_timer_params_set_ticks(¶ms, dmix->timer_ticks);
|
|
if (dmix->tread) {
|
|
filter = (1<<SND_TIMER_EVENT_TICK) |
|
|
dmix->timer_events;
|
|
@@ -1656,6 +1716,7 @@ int snd_pcm_direct_parse_open_conf(snd_c
|
|
rec->ipc_gid = -1;
|
|
rec->slowptr = 1;
|
|
rec->max_periods = 0;
|
|
+ rec->var_periodsize = 1;
|
|
|
|
/* read defaults */
|
|
if (snd_config_search(root, "defaults.pcm.dmix_max_periods", &n) >= 0) {
|
|
@@ -1762,6 +1823,13 @@ int snd_pcm_direct_parse_open_conf(snd_c
|
|
rec->max_periods = val;
|
|
continue;
|
|
}
|
|
+ if (strcmp(id, "var_periodsize") == 0) {
|
|
+ err = snd_config_get_bool(n);
|
|
+ if (err < 0)
|
|
+ return err;
|
|
+ rec->var_periodsize = err;
|
|
+ continue;
|
|
+ }
|
|
SNDERR("Unknown field %s", id);
|
|
return -EINVAL;
|
|
}
|
|
--- a/src/pcm/pcm_direct.h
|
|
+++ b/src/pcm/pcm_direct.h
|
|
@@ -147,12 +147,14 @@ struct snd_pcm_direct {
|
|
int tread: 1;
|
|
int timer_need_poll: 1;
|
|
unsigned int timer_events;
|
|
+ unsigned int timer_ticks;
|
|
int server_fd;
|
|
pid_t server_pid;
|
|
snd_timer_t *timer; /* timer used as poll_fd */
|
|
int interleaved; /* we have interleaved buffer */
|
|
int slowptr; /* use slow but more precise ptr updates */
|
|
int max_periods; /* max periods (-1 = fixed periods, 0 = max buffer size) */
|
|
+ int var_periodsize; /* allow variable period size if max_periods is != -1*/
|
|
unsigned int channels; /* client's channels */
|
|
unsigned int *bindings;
|
|
union {
|
|
@@ -326,6 +328,7 @@ struct snd_pcm_direct_open_conf {
|
|
int ipc_gid;
|
|
int slowptr;
|
|
int max_periods;
|
|
+ int var_periodsize;
|
|
snd_config_t *slave;
|
|
snd_config_t *bindings;
|
|
};
|
|
--- a/src/pcm/pcm_dmix.c
|
|
+++ b/src/pcm/pcm_dmix.c
|
|
@@ -1040,6 +1040,7 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp,
|
|
dmix->state = SND_PCM_STATE_OPEN;
|
|
dmix->slowptr = opts->slowptr;
|
|
dmix->max_periods = opts->max_periods;
|
|
+ dmix->var_periodsize = opts->var_periodsize;
|
|
dmix->sync_ptr = snd_pcm_dmix_sync_ptr;
|
|
|
|
retry:
|
|
--- a/src/pcm/pcm_dshare.c
|
|
+++ b/src/pcm/pcm_dshare.c
|
|
@@ -725,6 +725,7 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp
|
|
dshare->state = SND_PCM_STATE_OPEN;
|
|
dshare->slowptr = opts->slowptr;
|
|
dshare->max_periods = opts->max_periods;
|
|
+ dshare->var_periodsize = opts->var_periodsize;
|
|
dshare->sync_ptr = snd_pcm_dshare_sync_ptr;
|
|
|
|
retry:
|
|
--- a/src/pcm/pcm_dsnoop.c
|
|
+++ b/src/pcm/pcm_dsnoop.c
|
|
@@ -606,6 +606,7 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp
|
|
dsnoop->state = SND_PCM_STATE_OPEN;
|
|
dsnoop->slowptr = opts->slowptr;
|
|
dsnoop->max_periods = opts->max_periods;
|
|
+ dsnoop->var_periodsize = opts->var_periodsize;
|
|
dsnoop->sync_ptr = snd_pcm_dsnoop_sync_ptr;
|
|
|
|
retry:
|