alsa/0003-pcm-direct-allow-users-to-configure-different-period.patch
OBS User mrdocs 6977966888 Accepting request 483406 from home:tiwai:branches:multimedia:libs
- 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
2017-03-29 22:55:12 +00:00

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(&params, 1);
if (dmix->type != SND_PCM_TYPE_DSNOOP)
snd_timer_params_set_early_event(&params, 1);
- snd_timer_params_set_ticks(&params, 1);
+ snd_timer_params_set_ticks(&params, 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: