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
This commit is contained in:
OBS User mrdocs 2017-03-29 22:55:12 +00:00 committed by Git OBS Bridge
parent a577d8eaee
commit 6977966888
45 changed files with 4080 additions and 0 deletions

View File

@ -0,0 +1,43 @@
From 6ad2a9763d9aaab30c0470d039877b1bb61dda3b Mon Sep 17 00:00:00 2001
From: Mengdong Lin <mengdong.lin@linux.intel.com>
Date: Tue, 27 Dec 2016 18:08:58 +0800
Subject: [PATCH 01/43] ucm: Add ATTRIBUTE_UNUSED for unused parameters of
execute_component_seq()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
To fix the following warnings:
main.c: In function execute_component_seq:
main.c:489:24: warning: unused parameter value_list1 [-Wunused-parameter]
struct list_head *value_list1,
^
main.c:490:24: warning: unused parameter value_list2 [-Wunused-parameter]
struct list_head *value_list2,
^
main.c:491:24: warning: unused parameter value_list3 [-Wunused-parameter]
struct list_head *value_list3,
^
Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/ucm/main.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
--- a/src/ucm/main.c
+++ b/src/ucm/main.c
@@ -486,9 +486,9 @@ static int execute_sequence(snd_use_case
*/
static int execute_component_seq(snd_use_case_mgr_t *uc_mgr,
struct component_sequence *cmpt_seq,
- struct list_head *value_list1,
- struct list_head *value_list2,
- struct list_head *value_list3,
+ struct list_head *value_list1 ATTRIBUTE_UNUSED,
+ struct list_head *value_list2 ATTRIBUTE_UNUSED,
+ struct list_head *value_list3 ATTRIBUTE_UNUSED,
char *cdev)
{
struct use_case_device *device = cmpt_seq->device;

View File

@ -0,0 +1,24 @@
From 9ed4075f05a4242f32331f7f2c365767970f5003 Mon Sep 17 00:00:00 2001
From: Gustavo Zacarias <gustavo@zacarias.com.ar>
Date: Wed, 21 Dec 2016 19:46:34 -0300
Subject: [PATCH 02/43] ucm: parser needs limits.h
It's using PATH_MAX which is defined there, otherwise the build fails on
musl libc.
Signed-off-by: Gustavo Zacarias <gustavo@zacarias.com.ar>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/ucm/parser.c | 1 +
1 file changed, 1 insertion(+)
--- a/src/ucm/parser.c
+++ b/src/ucm/parser.c
@@ -32,6 +32,7 @@
#include "ucm_local.h"
#include <dirent.h>
+#include <limits.h>
/** The name of the environment variable containing the UCM directory */
#define ALSA_CONFIG_UCM_VAR "ALSA_CONFIG_UCM"

View File

@ -0,0 +1,237 @@
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:

View File

@ -0,0 +1,34 @@
From 8eeee1ab7d7db3110b7b3bb31cfb989304dced94 Mon Sep 17 00:00:00 2001
From: Alexander Jahn <ajahn@de.adit-jv.com>
Date: Fri, 30 Dec 2016 11:59:11 +0530
Subject: [PATCH 04/43] pcm: dshare: enable silence
This issue depends on system load - if the process using dshare is
scheduled fast enough, then there is no noise. A delay of e.g >~2ms
produces hearable noise.
Reproduction with instrumented aplay(sleep every 100th period for a
given time):
During the sleep time of 2000000us (2s) the hardware plays old samples
in a loop before xrun is detected and recovered after the sleep.
This is resolved by placing it in silence, in case of dshare plugin.
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 | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/src/pcm/pcm_direct.c
+++ b/src/pcm/pcm_direct.c
@@ -1161,7 +1161,8 @@ int snd_pcm_direct_initialize_slave(snd_
return ret;
}
- if (dmix->type != SND_PCM_TYPE_DMIX)
+ if (dmix->type != SND_PCM_TYPE_DMIX &&
+ dmix->type != SND_PCM_TYPE_DSHARE)
goto __skip_silencing;
ret = snd_pcm_sw_params_set_silence_threshold(spcm, &sw_params, 0);

View File

@ -0,0 +1,92 @@
From 7570e5d77514d8d8af387da04a010fa2ccaf543c Mon Sep 17 00:00:00 2001
From: "mahendran.k" <mahendran.kuppusamy@in.bosch.com>
Date: Fri, 30 Dec 2016 11:59:27 +0530
Subject: [PATCH 05/43] pcm: rate: fix the hw_ptr update until the boundary
available
For long time test case, the slave_hw_ptr will exceed the boundary
and wraparound the slave_hw_ptr. This slave boundary wraparound will
cause the rate->hw_ptr to wraparound irrespective of the
rate->boundary availability and due to that the available size goes
wrong.
Hence, to get the correct available size,
- Its necessary to increment the rate->hw_ptr upto the rate->boundary
and then wraparound the rate->hw_ptr.
- While handling fraction part of slave period, rounded value will be
introduced by input_frames(). To eliminate rounding issue on
rate->hw_ptr, subtract last rounded value from rate->hw_ptr and add
new rounded value of present slave_hw_ptr fraction part to
rate->hw_ptr.
Signed-off-by: mahendran.k <mahendran.kuppusamy@in.bosch.com>
Signed-off-by: Mounesh Sutar <mounesh_sutar@mentor.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_rate.c | 31 +++++++++++++++++++++++++------
1 file changed, 25 insertions(+), 6 deletions(-)
--- a/src/pcm/pcm_rate.c
+++ b/src/pcm/pcm_rate.c
@@ -50,7 +50,7 @@ typedef struct _snd_pcm_rate snd_pcm_rat
struct _snd_pcm_rate {
snd_pcm_generic_t gen;
- snd_pcm_uframes_t appl_ptr, hw_ptr;
+ snd_pcm_uframes_t appl_ptr, hw_ptr, last_slave_hw_ptr;
snd_pcm_uframes_t last_commit_ptr;
snd_pcm_uframes_t orig_avail_min;
snd_pcm_sw_params_t sw_params;
@@ -563,14 +563,31 @@ static inline void snd_pcm_rate_sync_hwp
{
snd_pcm_rate_t *rate = pcm->private_data;
+ snd_pcm_sframes_t slave_hw_ptr_diff = slave_hw_ptr - rate->last_slave_hw_ptr;
+ snd_pcm_sframes_t last_slave_hw_ptr_frac;
+
if (pcm->stream != SND_PCM_STREAM_PLAYBACK)
return;
- /* FIXME: boundary overlap of slave hw_ptr isn't evaluated here!
- * e.g. if slave rate is small...
+
+ if (slave_hw_ptr_diff < 0)
+ slave_hw_ptr_diff += rate->gen.slave->boundary; /* slave boundary wraparound */
+ else if (slave_hw_ptr_diff == 0)
+ return;
+ last_slave_hw_ptr_frac = rate->last_slave_hw_ptr % rate->gen.slave->period_size;
+ /* While handling fraction part fo slave period, rounded value will be
+ * introduced by input_frames().
+ * To eliminate rounding issue on rate->hw_ptr, subtract last rounded
+ * value from rate->hw_ptr and add new rounded value of present
+ * slave_hw_ptr fraction part to rate->hw_ptr. Hence,
+ * rate->hw_ptr += [ (no. of updated slave periods * pcm rate period size) -
+ * fractional part of last_slave_hw_ptr rounded value +
+ * fractional part of updated slave hw ptr's rounded value ]
*/
- rate->hw_ptr =
- (slave_hw_ptr / rate->gen.slave->period_size) * pcm->period_size +
- rate->ops.input_frames(rate->obj, slave_hw_ptr % rate->gen.slave->period_size);
+ rate->hw_ptr += (
+ (((last_slave_hw_ptr_frac + slave_hw_ptr_diff) / rate->gen.slave->period_size) * pcm->period_size) -
+ rate->ops.input_frames(rate->obj, last_slave_hw_ptr_frac) +
+ rate->ops.input_frames(rate->obj, (last_slave_hw_ptr_frac + slave_hw_ptr_diff) % rate->gen.slave->period_size));
+ rate->last_slave_hw_ptr = slave_hw_ptr;
rate->hw_ptr %= pcm->boundary;
}
@@ -635,6 +652,7 @@ static int snd_pcm_rate_prepare(snd_pcm_
return err;
*pcm->hw.ptr = 0;
*pcm->appl.ptr = 0;
+ rate->last_slave_hw_ptr = 0;
err = snd_pcm_rate_init(pcm);
if (err < 0)
return err;
@@ -650,6 +668,7 @@ static int snd_pcm_rate_reset(snd_pcm_t
return err;
*pcm->hw.ptr = 0;
*pcm->appl.ptr = 0;
+ rate->last_slave_hw_ptr = 0;
err = snd_pcm_rate_init(pcm);
if (err < 0)
return err;

View File

@ -0,0 +1,101 @@
From 88e4ae27bb4e47029ed57cc8e02fb1ddf2157fd9 Mon Sep 17 00:00:00 2001
From: Andreas Pape <apape@de.adit-jv.com>
Date: Mon, 19 Dec 2016 12:37:50 +0900
Subject: [PATCH 06/43] plugin: dynamically update avail_min on slave
mmapped capture access on some plugins can fetch data from
slave in the 'background'. A subsequent snd_pcm_wait waits
for too long time to reach avail_min threshold again.
Waiting too long leads to xruns on other devices waiting for
the capture data.
As a fix the avail_min on slave is recalculated dynamically.
V2: updated patch to fix within 80 characters per line
Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_plugin.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 63 insertions(+), 1 deletion(-)
--- a/src/pcm/pcm_plugin.c
+++ b/src/pcm/pcm_plugin.c
@@ -535,6 +535,68 @@ static int snd_pcm_plugin_status(snd_pcm
return 0;
}
+static int snd_pcm_plugin_may_wait_for_avail_min(snd_pcm_t *pcm,
+ snd_pcm_uframes_t avail)
+{
+ if (pcm->stream == SND_PCM_STREAM_CAPTURE &&
+ pcm->access != SND_PCM_ACCESS_RW_INTERLEAVED &&
+ pcm->access != SND_PCM_ACCESS_RW_NONINTERLEAVED) {
+ /* mmap access on capture device already consumes data from
+ * slave in avail_update operation. Entering snd_pcm_wait after
+ * having already consumed some fragments leads to waiting for
+ * too long time, as slave will unnecessarily wait for avail_min
+ * condition reached again. To avoid unnecessary wait times we
+ * adapt the avail_min threshold on slave dynamically. Just
+ * modifying slave->avail_min as a shortcut and lightweight
+ * solution does not work for all slave plugin types and in
+ * addition it will not propagate the change through all
+ * downstream plugins, so we have to use the sw_params API.
+ * note: reading fragmental parts from slave will only happen
+ * in case
+ * a) the slave can provide contineous hw_ptr between periods
+ * b) avail_min does not match one slave_period
+ */
+ snd_pcm_plugin_t *plugin = pcm->private_data;
+ snd_pcm_t *slave = plugin->gen.slave;
+ snd_pcm_uframes_t needed_slave_avail_min;
+ snd_pcm_sframes_t available;
+
+ /* update, as it might have changed. This will also call
+ * avail_update on slave and also can return error
+ */
+ available = snd_pcm_avail_update(pcm);
+ if (available < 0)
+ return 0;
+
+ if (available >= pcm->avail_min)
+ /* don't wait at all. As we can't configure avail_min
+ * of slave to 0 return here
+ */
+ return 0;
+
+ needed_slave_avail_min = pcm->avail_min - available;
+ if (slave->avail_min != needed_slave_avail_min) {
+ snd_pcm_sw_params_t *swparams;
+ snd_pcm_sw_params_alloca(&swparams);
+ /* pray that changing sw_params while running is
+ * properly implemented in all downstream plugins...
+ * it's legal but not commonly used.
+ */
+ snd_pcm_sw_params_current(slave, swparams);
+ /* snd_pcm_sw_params_set_avail_min() restricts setting
+ * to >= period size. This conflicts at least with our
+ * dshare patch which allows combining multiple periods
+ * or with slaves which return hw postions between
+ * periods -> set directly in sw_param structure
+ */
+ swparams->avail_min = needed_slave_avail_min;
+ snd_pcm_sw_params(slave, swparams);
+ }
+ avail = available;
+ }
+ return snd_pcm_generic_may_wait_for_avail_min(pcm, avail);
+}
+
const snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = {
.status = snd_pcm_plugin_status,
.state = snd_pcm_generic_state,
@@ -564,7 +626,7 @@ const snd_pcm_fast_ops_t snd_pcm_plugin_
.poll_descriptors_count = snd_pcm_generic_poll_descriptors_count,
.poll_descriptors = snd_pcm_generic_poll_descriptors,
.poll_revents = snd_pcm_generic_poll_revents,
- .may_wait_for_avail_min = snd_pcm_generic_may_wait_for_avail_min,
+ .may_wait_for_avail_min = snd_pcm_plugin_may_wait_for_avail_min,
};
#endif

View File

@ -0,0 +1,57 @@
From ff1f669df4b05da3c44dc4a79ce00233fe9de9b7 Mon Sep 17 00:00:00 2001
From: Andreas Pape <apape@de.adit-jv.com>
Date: Mon, 19 Dec 2016 12:37:51 +0900
Subject: [PATCH 07/43] rate: dynamic update avail_min on slave
Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_plugin.c | 4 ++--
src/pcm/pcm_plugin.h | 3 +++
src/pcm/pcm_rate.c | 2 +-
3 files changed, 6 insertions(+), 3 deletions(-)
--- a/src/pcm/pcm_plugin.c
+++ b/src/pcm/pcm_plugin.c
@@ -535,8 +535,8 @@ static int snd_pcm_plugin_status(snd_pcm
return 0;
}
-static int snd_pcm_plugin_may_wait_for_avail_min(snd_pcm_t *pcm,
- snd_pcm_uframes_t avail)
+int snd_pcm_plugin_may_wait_for_avail_min(snd_pcm_t *pcm,
+ snd_pcm_uframes_t avail)
{
if (pcm->stream == SND_PCM_STREAM_CAPTURE &&
pcm->access != SND_PCM_ACCESS_RW_INTERLEAVED &&
--- a/src/pcm/pcm_plugin.h
+++ b/src/pcm/pcm_plugin.h
@@ -50,6 +50,8 @@ typedef struct {
/* make local functions really local */
#define snd_pcm_plugin_init \
snd1_pcm_plugin_init
+#define snd_pcm_plugin_may_wait_for_avail_min \
+ snd1_pcm_plugin_may_wait_for_avail_min
#define snd_pcm_plugin_fast_ops \
snd1_pcm_plugin_fast_ops
#define snd_pcm_plugin_undo_read_generic \
@@ -64,6 +66,7 @@ typedef struct {
void snd_pcm_plugin_init(snd_pcm_plugin_t *plugin);
snd_pcm_sframes_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
snd_pcm_sframes_t snd_pcm_plugin_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
+int snd_pcm_plugin_may_wait_for_avail_min(snd_pcm_t *pcm, snd_pcm_uframes_t avail);
extern const snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops;
--- a/src/pcm/pcm_rate.c
+++ b/src/pcm/pcm_rate.c
@@ -1213,7 +1213,7 @@ static const snd_pcm_fast_ops_t snd_pcm_
.poll_descriptors_count = snd_pcm_generic_poll_descriptors_count,
.poll_descriptors = snd_pcm_generic_poll_descriptors,
.poll_revents = snd_pcm_rate_poll_revents,
- .may_wait_for_avail_min = snd_pcm_generic_may_wait_for_avail_min,
+ .may_wait_for_avail_min = snd_pcm_plugin_may_wait_for_avail_min,
};
static const snd_pcm_ops_t snd_pcm_rate_ops = {

View File

@ -0,0 +1,42 @@
From 6f7eaf92e7de73eb32bd97bad83a14fcb0f408f7 Mon Sep 17 00:00:00 2001
From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Date: Wed, 30 Nov 2016 00:44:32 +0900
Subject: [PATCH 08/43] topology: fix unused-const-variable warning
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Last year, unused static const variable was added, then compiler generates
a below warning.
dapm.c:43:30: warning: widget_control_map defined but not used [-Wunused-const-variable=]
static const struct map_elem widget_control_map[] = {
^~~~~~~~~~~~~~~~~~
This commit removes it.
Fixes: 01a0e1a1c219 ("topology: Add DAPM object parser")
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Acked-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/topology/dapm.c | 8 --------
1 file changed, 8 deletions(-)
--- a/src/topology/dapm.c
+++ b/src/topology/dapm.c
@@ -39,14 +39,6 @@ static const struct map_elem widget_map[
{"dai_link", SND_SOC_TPLG_DAPM_DAI_LINK},
};
-/* mapping of widget kcontrol text names to types */
-static const struct map_elem widget_control_map[] = {
- {"volsw", SND_SOC_TPLG_DAPM_CTL_VOLSW},
- {"enum_double", SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE},
- {"enum_virt", SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT},
- {"enum_value", SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE},
-};
-
static int lookup_widget(const char *w)
{
unsigned int i;

View File

@ -0,0 +1,77 @@
From 1eddf1f918845d1e6cbcac5516319b20cad80f2f Mon Sep 17 00:00:00 2001
From: Adam Goode <agoode@google.com>
Date: Tue, 3 Jan 2017 08:33:42 -0500
Subject: [PATCH 09/43] seq: improve documentation about new get pid/card
functions
Document the technique for determining if the running kernel supports
the new snd_seq_client_info_get_pid and snd_seq_client_info_get_card
functions. Also add a little information about how to use these
functions and add some cross references.
Signed-off-by: Adam Goode <agoode@google.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/seq/seq.c | 44 ++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 42 insertions(+), 2 deletions(-)
--- a/src/seq/seq.c
+++ b/src/seq/seq.c
@@ -1530,7 +1530,25 @@ int snd_seq_client_info_get_error_bounce
* \param info client_info container
* \return card number or -1 if value is not available.
*
- * Only available for SND_SEQ_KERNEL_CLIENT clients.
+ * Only available for #SND_SEQ_KERNEL_CLIENT clients.
+ *
+ * The card number can be used to query state about the hardware
+ * device providing this client, by concatenating <code>"hw:CARD="</code>
+ * with the card number and using it as the <code>name</code> parameter
+ * to #snd_ctl_open().
+ *
+ * \note
+ * The return value of -1 is returned for two different conditions: when the
+ * running kernel does not support this operation, and when the client
+ * does not have a hardware card attached. See
+ * #snd_seq_client_info_get_pid() for a way to determine if the
+ * currently running kernel has support for this operation.
+ *
+ * \sa snd_seq_client_info_get_pid(),
+ * snd_card_get_name(),
+ * snd_card_get_longname(),
+ * snd_ctl_open(),
+ * snd_ctl_card_info()
*/
int snd_seq_client_info_get_card(const snd_seq_client_info_t *info)
{
@@ -1543,7 +1561,29 @@ int snd_seq_client_info_get_card(const s
* \param info client_info container
* \return pid or -1 if value is not available.
*
- * Only available for SND_SEQ_USER_CLIENT clients.
+ * Only available for #SND_SEQ_USER_CLIENT clients.
+ *
+ * \note
+ * The functionality for getting a client's PID and getting a
+ * client's card was added to the kernel at the same time, so you can
+ * use this function to determine if the running kernel
+ * supports reporting these values. If your own client has a valid
+ * PID as reported by this function, then the running kernel supports
+ * both #snd_seq_client_info_get_card() and #snd_seq_client_info_get_pid().
+ *
+ * \note
+ * Example code for determining kernel support:
+ * \code
+ * int is_get_card_or_pid_supported(snd_seq_t *seq)
+ * {
+ * snd_seq_client_info_t *my_client_info;
+ * snd_seq_client_info_alloca(&my_client_info);
+ * snd_seq_get_client_info(seq, my_client_info);
+ * return snd_seq_client_info_get_pid(my_client_info) != -1;
+ * }
+ * \endcode
+ *
+ * \sa snd_seq_client_info_get_card()
*/
int snd_seq_client_info_get_pid(const snd_seq_client_info_t *info)
{

View File

@ -0,0 +1,38 @@
From 3f0dc404f16af58d20b4489b0daafcf87555dfb7 Mon Sep 17 00:00:00 2001
From: Mounesh Sutar <sutar.mounesh@gmail.com>
Date: Tue, 10 Jan 2017 12:03:17 +0530
Subject: [PATCH 10/43] pcm: direct: returning semop error code for semaphore
up/down failures
Signed-off-by: Mounesh Sutar <sutar.mounesh@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_direct.h | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
--- a/src/pcm/pcm_direct.h
+++ b/src/pcm/pcm_direct.h
@@ -263,7 +263,10 @@ static inline int snd_pcm_direct_semapho
{
struct sembuf op[2] = { { sem_num, 0, 0 }, { sem_num, 1, SEM_UNDO } };
int err = semop(dmix->semid, op, 2);
- if (err == 0) dmix->locked[sem_num]++;
+ if (err == 0)
+ dmix->locked[sem_num]++;
+ else if (err == -1)
+ err = -errno;
return err;
}
@@ -271,7 +274,10 @@ static inline int snd_pcm_direct_semapho
{
struct sembuf op = { sem_num, -1, SEM_UNDO | IPC_NOWAIT };
int err = semop(dmix->semid, &op, 1);
- if (err == 0) dmix->locked[sem_num]--;
+ if (err == 0)
+ dmix->locked[sem_num]--;
+ else if (err == -1)
+ err = -errno;
return err;
}

View File

@ -0,0 +1,370 @@
From 1a9bd0f0448106b917ae7f7bedccfcbf6ce84802 Mon Sep 17 00:00:00 2001
From: Andreas Pape <apape@de.adit-jv.com>
Date: Tue, 10 Jan 2017 12:03:36 +0530
Subject: [PATCH 11/43] pcm: direct: Fix for sync issue on xrun recover
If using very short periods, DSHARE/DSNOOP/DMIX may report underruns while in
status 'prepared'. This prohibits correct recovery. Now slave xrun conditions
for DSHARE/DSNOOP/DMIX are being handled properly.
Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
Signed-off-by: Joshua Frkuska <joshua_frkuska@mentor.com>
Signed-off-by: Mounesh Sutar <mounesh_sutar@mentor.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_direct.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++
src/pcm/pcm_direct.h | 5 ++
src/pcm/pcm_dmix.c | 27 ++++++++++---
src/pcm/pcm_dshare.c | 29 +++++++++++---
src/pcm/pcm_dsnoop.c | 15 ++++++-
5 files changed, 162 insertions(+), 16 deletions(-)
--- a/src/pcm/pcm_direct.c
+++ b/src/pcm/pcm_direct.c
@@ -550,6 +550,101 @@ int snd_pcm_direct_timer_stop(snd_pcm_di
return 0;
}
+/*
+ * Recover slave on XRUN.
+ * Even if direct plugins disable xrun detection, there might be an xrun
+ * raised directly by some drivers.
+ * The first client recovers slave pcm.
+ * Each client needs to execute sw xrun handling afterwards
+ */
+int snd_pcm_direct_slave_recover(snd_pcm_direct_t *direct)
+{
+ int ret;
+ int semerr;
+
+ semerr = snd_pcm_direct_semaphore_down(direct,
+ DIRECT_IPC_SEM_CLIENT);
+ if (semerr < 0) {
+ SNDERR("SEMDOWN FAILED with err %d", semerr);
+ return semerr;
+ }
+
+ if (snd_pcm_state(direct->spcm) != SND_PCM_STATE_XRUN) {
+ /* ignore... someone else already did recovery */
+ semerr = snd_pcm_direct_semaphore_up(direct,
+ DIRECT_IPC_SEM_CLIENT);
+ if (semerr < 0) {
+ SNDERR("SEMUP FAILED with err %d", semerr);
+ return semerr;
+ }
+ return 0;
+ }
+
+ ret = snd_pcm_prepare(direct->spcm);
+ if (ret < 0) {
+ SNDERR("recover: unable to prepare slave");
+ semerr = snd_pcm_direct_semaphore_up(direct,
+ DIRECT_IPC_SEM_CLIENT);
+ if (semerr < 0) {
+ SNDERR("SEMUP FAILED with err %d", semerr);
+ return semerr;
+ }
+ return ret;
+ }
+
+ if (direct->type == SND_PCM_TYPE_DSHARE) {
+ const snd_pcm_channel_area_t *dst_areas;
+ dst_areas = snd_pcm_mmap_areas(direct->spcm);
+ snd_pcm_areas_silence(dst_areas, 0, direct->spcm->channels,
+ direct->spcm->buffer_size,
+ direct->spcm->format);
+ }
+
+ ret = snd_pcm_start(direct->spcm);
+ if (ret < 0) {
+ SNDERR("recover: unable to start slave");
+ semerr = snd_pcm_direct_semaphore_up(direct,
+ DIRECT_IPC_SEM_CLIENT);
+ if (semerr < 0) {
+ SNDERR("SEMUP FAILED with err %d", semerr);
+ return semerr;
+ }
+ return ret;
+ }
+ direct->shmptr->recoveries++;
+ semerr = snd_pcm_direct_semaphore_up(direct,
+ DIRECT_IPC_SEM_CLIENT);
+ if (semerr < 0) {
+ SNDERR("SEMUP FAILED with err %d", semerr);
+ return semerr;
+ }
+ return 0;
+}
+
+/*
+ * enter xrun state, if slave xrun occurred
+ * @return: 0 - no xrun >0: xrun happened
+ */
+int snd_pcm_direct_client_chk_xrun(snd_pcm_direct_t *direct, snd_pcm_t *pcm)
+{
+ if (direct->shmptr->recoveries != direct->recoveries) {
+ /* no matter how many xruns we missed -
+ * so don't increment but just update to actual counter
+ */
+ direct->recoveries = direct->shmptr->recoveries;
+ pcm->fast_ops->drop(pcm);
+ /* trigger_tstamp update is missing in drop callbacks */
+ gettimestamp(&direct->trigger_tstamp, pcm->tstamp_type);
+ /* no timer clear:
+ * if slave already entered xrun again the event is lost.
+ * snd_pcm_direct_clear_timer_queue(direct);
+ */
+ direct->state = SND_PCM_STATE_XRUN;
+ return 1;
+ }
+ return 0;
+}
+
int snd_pcm_direct_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
{
snd_pcm_direct_t *dmix = pcm->private_data;
@@ -572,6 +667,12 @@ int snd_pcm_direct_poll_revents(snd_pcm_
}
switch (snd_pcm_state(dmix->spcm)) {
case SND_PCM_STATE_XRUN:
+ /* recover slave and update client state to xrun
+ * before returning POLLERR
+ */
+ snd_pcm_direct_slave_recover(dmix);
+ snd_pcm_direct_client_chk_xrun(dmix, pcm);
+ /* fallthrough */
case SND_PCM_STATE_SUSPENDED:
case SND_PCM_STATE_SETUP:
events |= POLLERR;
@@ -1382,6 +1483,7 @@ int snd_pcm_direct_open_secondary_client
dmix->slave_buffer_size = spcm->buffer_size;
dmix->slave_period_size = dmix->shmptr->s.period_size;
dmix->slave_boundary = spcm->boundary;
+ dmix->recoveries = dmix->shmptr->recoveries;
ret = snd_pcm_mmap(spcm);
if (ret < 0) {
--- a/src/pcm/pcm_direct.h
+++ b/src/pcm/pcm_direct.h
@@ -66,6 +66,7 @@ typedef struct {
char socket_name[256]; /* name of communication socket */
snd_pcm_type_t type; /* PCM type (currently only hw) */
int use_server;
+ unsigned int recoveries; /* no of executed recoveries on slave*/
struct {
unsigned int format;
snd_interval_t rate;
@@ -157,6 +158,7 @@ struct snd_pcm_direct {
int var_periodsize; /* allow variable period size if max_periods is != -1*/
unsigned int channels; /* client's channels */
unsigned int *bindings;
+ unsigned int recoveries; /* mirror of executed recoveries on slave */
union {
struct {
int shmid_sum; /* IPC global sum ring buffer memory identification */
@@ -324,7 +326,8 @@ int snd_pcm_direct_open_secondary_client
snd_pcm_chmap_query_t **snd_pcm_direct_query_chmaps(snd_pcm_t *pcm);
snd_pcm_chmap_t *snd_pcm_direct_get_chmap(snd_pcm_t *pcm);
int snd_pcm_direct_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map);
-
+int snd_pcm_direct_slave_recover(snd_pcm_direct_t *direct);
+int snd_pcm_direct_client_chk_xrun(snd_pcm_direct_t *direct, snd_pcm_t *pcm);
int snd_timer_async(snd_timer_t *timer, int sig, pid_t pid);
struct timespec snd_pcm_hw_fast_tstamp(snd_pcm_t *pcm);
--- a/src/pcm/pcm_dmix.c
+++ b/src/pcm/pcm_dmix.c
@@ -434,15 +434,21 @@ static int snd_pcm_dmix_sync_ptr0(snd_pc
static int snd_pcm_dmix_sync_ptr(snd_pcm_t *pcm)
{
snd_pcm_direct_t *dmix = pcm->private_data;
+ int err;
switch (snd_pcm_state(dmix->spcm)) {
case SND_PCM_STATE_DISCONNECTED:
dmix->state = SND_PCM_STATE_DISCONNECTED;
return -ENODEV;
+ case SND_PCM_STATE_XRUN:
+ if ((err = snd_pcm_direct_slave_recover(dmix)) < 0)
+ return err;
+ break;
default:
break;
}
-
+ if (snd_pcm_direct_client_chk_xrun(dmix, pcm))
+ return -EPIPE;
if (dmix->slowptr)
snd_pcm_hwsync(dmix->spcm);
@@ -828,12 +834,16 @@ static snd_pcm_sframes_t snd_pcm_dmix_mm
switch (snd_pcm_state(dmix->spcm)) {
case SND_PCM_STATE_XRUN:
- return -EPIPE;
+ if ((err = snd_pcm_direct_slave_recover(dmix)) < 0)
+ return err;
+ break;
case SND_PCM_STATE_SUSPENDED:
return -ESTRPIPE;
default:
break;
}
+ if (snd_pcm_direct_client_chk_xrun(dmix, pcm))
+ return -EPIPE;
if (! size)
return 0;
snd_pcm_mmap_appl_forward(pcm, size);
@@ -841,8 +851,10 @@ static snd_pcm_sframes_t snd_pcm_dmix_mm
if ((err = snd_pcm_dmix_start_timer(pcm, dmix)) < 0)
return err;
} else if (dmix->state == SND_PCM_STATE_RUNNING ||
- dmix->state == SND_PCM_STATE_DRAINING)
- snd_pcm_dmix_sync_ptr(pcm);
+ dmix->state == SND_PCM_STATE_DRAINING) {
+ if ((err = snd_pcm_dmix_sync_ptr(pcm)) < 0)
+ return err;
+ }
if (dmix->state == SND_PCM_STATE_RUNNING ||
dmix->state == SND_PCM_STATE_DRAINING) {
/* ok, we commit the changes after the validation of area */
@@ -858,10 +870,13 @@ static snd_pcm_sframes_t snd_pcm_dmix_mm
static snd_pcm_sframes_t snd_pcm_dmix_avail_update(snd_pcm_t *pcm)
{
snd_pcm_direct_t *dmix = pcm->private_data;
+ int err;
if (dmix->state == SND_PCM_STATE_RUNNING ||
- dmix->state == SND_PCM_STATE_DRAINING)
- snd_pcm_dmix_sync_ptr(pcm);
+ dmix->state == SND_PCM_STATE_DRAINING) {
+ if ((err = snd_pcm_dmix_sync_ptr(pcm)) < 0)
+ return err;
+ }
return snd_pcm_mmap_playback_avail(pcm);
}
--- a/src/pcm/pcm_dshare.c
+++ b/src/pcm/pcm_dshare.c
@@ -162,7 +162,7 @@ static int snd_pcm_dshare_sync_ptr0(snd_
snd_pcm_direct_t *dshare = pcm->private_data;
snd_pcm_uframes_t old_slave_hw_ptr, avail;
snd_pcm_sframes_t diff;
-
+
old_slave_hw_ptr = dshare->slave_hw_ptr;
dshare->slave_hw_ptr = slave_hw_ptr;
diff = slave_hw_ptr - old_slave_hw_ptr;
@@ -202,15 +202,21 @@ static int snd_pcm_dshare_sync_ptr0(snd_
static int snd_pcm_dshare_sync_ptr(snd_pcm_t *pcm)
{
snd_pcm_direct_t *dshare = pcm->private_data;
+ int err;
switch (snd_pcm_state(dshare->spcm)) {
case SND_PCM_STATE_DISCONNECTED:
dshare->state = SNDRV_PCM_STATE_DISCONNECTED;
return -ENODEV;
+ case SND_PCM_STATE_XRUN:
+ if ((err = snd_pcm_direct_slave_recover(dshare)) < 0)
+ return err;
+ break;
default:
break;
}
-
+ if (snd_pcm_direct_client_chk_xrun(dshare, pcm))
+ return -EPIPE;
if (dshare->slowptr)
snd_pcm_hwsync(dshare->spcm);
@@ -516,12 +522,16 @@ static snd_pcm_sframes_t snd_pcm_dshare_
switch (snd_pcm_state(dshare->spcm)) {
case SND_PCM_STATE_XRUN:
- return -EPIPE;
+ if ((err = snd_pcm_direct_slave_recover(dshare)) < 0)
+ return err;
+ break;
case SND_PCM_STATE_SUSPENDED:
return -ESTRPIPE;
default:
break;
}
+ if (snd_pcm_direct_client_chk_xrun(dshare, pcm))
+ return -EPIPE;
if (! size)
return 0;
snd_pcm_mmap_appl_forward(pcm, size);
@@ -529,8 +539,10 @@ static snd_pcm_sframes_t snd_pcm_dshare_
if ((err = snd_pcm_dshare_start_timer(dshare)) < 0)
return err;
} else if (dshare->state == SND_PCM_STATE_RUNNING ||
- dshare->state == SND_PCM_STATE_DRAINING)
- snd_pcm_dshare_sync_ptr(pcm);
+ dshare->state == SND_PCM_STATE_DRAINING) {
+ if ((err = snd_pcm_dshare_sync_ptr(pcm)) < 0)
+ return err;
+ }
if (dshare->state == SND_PCM_STATE_RUNNING ||
dshare->state == SND_PCM_STATE_DRAINING) {
/* ok, we commit the changes after the validation of area */
@@ -546,10 +558,13 @@ static snd_pcm_sframes_t snd_pcm_dshare_
static snd_pcm_sframes_t snd_pcm_dshare_avail_update(snd_pcm_t *pcm)
{
snd_pcm_direct_t *dshare = pcm->private_data;
+ int err;
if (dshare->state == SND_PCM_STATE_RUNNING ||
- dshare->state == SND_PCM_STATE_DRAINING)
- snd_pcm_dshare_sync_ptr(pcm);
+ dshare->state == SND_PCM_STATE_DRAINING) {
+ if ((err = snd_pcm_dshare_sync_ptr(pcm)) < 0)
+ return err;
+ }
return snd_pcm_mmap_playback_avail(pcm);
}
--- a/src/pcm/pcm_dsnoop.c
+++ b/src/pcm/pcm_dsnoop.c
@@ -132,14 +132,21 @@ static int snd_pcm_dsnoop_sync_ptr(snd_p
snd_pcm_direct_t *dsnoop = pcm->private_data;
snd_pcm_uframes_t slave_hw_ptr, old_slave_hw_ptr, avail;
snd_pcm_sframes_t diff;
-
+ int err;
+
switch (snd_pcm_state(dsnoop->spcm)) {
case SND_PCM_STATE_DISCONNECTED:
dsnoop->state = SNDRV_PCM_STATE_DISCONNECTED;
return -ENODEV;
+ case SND_PCM_STATE_XRUN:
+ if ((err = snd_pcm_direct_slave_recover(dsnoop)) < 0)
+ return err;
+ break;
default:
break;
}
+ if (snd_pcm_direct_client_chk_xrun(dsnoop, pcm))
+ return -EPIPE;
if (dsnoop->slowptr)
snd_pcm_hwsync(dsnoop->spcm);
old_slave_hw_ptr = dsnoop->slave_hw_ptr;
@@ -410,12 +417,16 @@ static snd_pcm_sframes_t snd_pcm_dsnoop_
switch (snd_pcm_state(dsnoop->spcm)) {
case SND_PCM_STATE_XRUN:
- return -EPIPE;
+ if ((err = snd_pcm_direct_slave_recover(dsnoop)) < 0)
+ return err;
+ break;
case SND_PCM_STATE_SUSPENDED:
return -ESTRPIPE;
default:
break;
}
+ if (snd_pcm_direct_client_chk_xrun(dsnoop, pcm))
+ return -EPIPE;
if (dsnoop->state == SND_PCM_STATE_RUNNING) {
err = snd_pcm_dsnoop_sync_ptr(pcm);
if (err < 0)

View File

@ -0,0 +1,184 @@
From 789ee39727a12d6573b4d79e9cd7a375e6b8b005 Mon Sep 17 00:00:00 2001
From: Andreas Pape <apape@de.adit-jv.com>
Date: Tue, 10 Jan 2017 12:03:54 +0530
Subject: [PATCH 12/43] pcm: direct: check state before enter poll on timer
To avoid the chances of timeout, we need to check the enter poll
in state xrun.
Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
Signed-off-by: Mounesh Sutar <mounesh_sutar@mentor.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_direct.c | 40 ++++++++++++++++++++++++++++++++++++++++
src/pcm/pcm_direct.h | 2 ++
src/pcm/pcm_dmix.c | 9 +++++++--
src/pcm/pcm_dshare.c | 9 +++++++--
src/pcm/pcm_dsnoop.c | 9 +++++++--
5 files changed, 63 insertions(+), 6 deletions(-)
--- a/src/pcm/pcm_direct.c
+++ b/src/pcm/pcm_direct.c
@@ -645,6 +645,46 @@ int snd_pcm_direct_client_chk_xrun(snd_p
return 0;
}
+/*
+ * This is the only operation guaranteed to be called before entering poll().
+ * Direct plugins use fd of snd_timer to poll on, these timers do NOT check
+ * state of substream in kernel by intention.
+ * Only the enter to xrun might be notified once (SND_TIMER_EVENT_MSTOP).
+ * If xrun event was not correctly handled or was ignored it will never be
+ * evaluated again afterwards.
+ * This will result in snd_pcm_wait() always returning timeout.
+ * In contrast poll() on pcm hardware checks ALSA state and will immediately
+ * return POLLERR on XRUN.
+ *
+ * To prevent timeout and applications endlessly spinning without xrun
+ * detected we add a state check here which may trigger the xrun sequence.
+ *
+ * return count of filled descriptors or negative error code
+ */
+int snd_pcm_direct_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds,
+ unsigned int space)
+{
+ if (pcm->poll_fd < 0) {
+ SNDMSG("poll_fd < 0");
+ return -EIO;
+ }
+ if (space >= 1 && pfds) {
+ pfds->fd = pcm->poll_fd;
+ pfds->events = pcm->poll_events | POLLERR | POLLNVAL;
+ } else {
+ return 0;
+ }
+
+ /* this will also evaluate slave state and enter xrun if necessary */
+ switch (snd_pcm_state(pcm)) {
+ case SND_PCM_STATE_XRUN:
+ return -EPIPE;
+ default:
+ break;
+ }
+ return 1;
+}
+
int snd_pcm_direct_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
{
snd_pcm_direct_t *dmix = pcm->private_data;
--- a/src/pcm/pcm_direct.h
+++ b/src/pcm/pcm_direct.h
@@ -307,6 +307,8 @@ int snd_pcm_direct_parse_bindings(snd_pc
snd_config_t *cfg);
int snd_pcm_direct_nonblock(snd_pcm_t *pcm, int nonblock);
int snd_pcm_direct_async(snd_pcm_t *pcm, int sig, pid_t pid);
+int snd_pcm_direct_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds,
+ unsigned int space);
int snd_pcm_direct_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
int snd_pcm_direct_info(snd_pcm_t *pcm, snd_pcm_info_t * info);
int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
--- a/src/pcm/pcm_dmix.c
+++ b/src/pcm/pcm_dmix.c
@@ -462,17 +462,22 @@ static int snd_pcm_dmix_sync_ptr(snd_pcm
static snd_pcm_state_t snd_pcm_dmix_state(snd_pcm_t *pcm)
{
snd_pcm_direct_t *dmix = pcm->private_data;
+ int err;
snd_pcm_state_t state;
state = snd_pcm_state(dmix->spcm);
switch (state) {
- case SND_PCM_STATE_XRUN:
case SND_PCM_STATE_SUSPENDED:
case SND_PCM_STATE_DISCONNECTED:
dmix->state = state;
return state;
+ case SND_PCM_STATE_XRUN:
+ if ((err = snd_pcm_direct_slave_recover(dmix)) < 0)
+ return err;
+ break;
default:
break;
}
+ snd_pcm_direct_client_chk_xrun(dmix, pcm);
if (dmix->state == STATE_RUN_PENDING)
return SNDRV_PCM_STATE_RUNNING;
return dmix->state;
@@ -968,7 +973,7 @@ static const snd_pcm_fast_ops_t snd_pcm_
.avail_update = snd_pcm_dmix_avail_update,
.mmap_commit = snd_pcm_dmix_mmap_commit,
.htimestamp = snd_pcm_dmix_htimestamp,
- .poll_descriptors = NULL,
+ .poll_descriptors = snd_pcm_direct_poll_descriptors,
.poll_descriptors_count = NULL,
.poll_revents = snd_pcm_dmix_poll_revents,
};
--- a/src/pcm/pcm_dshare.c
+++ b/src/pcm/pcm_dshare.c
@@ -255,17 +255,22 @@ static int snd_pcm_dshare_status(snd_pcm
static snd_pcm_state_t snd_pcm_dshare_state(snd_pcm_t *pcm)
{
snd_pcm_direct_t *dshare = pcm->private_data;
+ int err;
snd_pcm_state_t state;
state = snd_pcm_state(dshare->spcm);
switch (state) {
- case SND_PCM_STATE_XRUN:
case SND_PCM_STATE_SUSPENDED:
case SND_PCM_STATE_DISCONNECTED:
dshare->state = state;
return state;
+ case SND_PCM_STATE_XRUN:
+ if ((err = snd_pcm_direct_slave_recover(dshare)) < 0)
+ return err;
+ break;
default:
break;
}
+ snd_pcm_direct_client_chk_xrun(dshare, pcm);
if (dshare->state == STATE_RUN_PENDING)
return SNDRV_PCM_STATE_RUNNING;
return dshare->state;
@@ -646,7 +651,7 @@ static const snd_pcm_fast_ops_t snd_pcm_
.avail_update = snd_pcm_dshare_avail_update,
.mmap_commit = snd_pcm_dshare_mmap_commit,
.htimestamp = snd_pcm_dshare_htimestamp,
- .poll_descriptors = NULL,
+ .poll_descriptors = snd_pcm_direct_poll_descriptors,
.poll_descriptors_count = NULL,
.poll_revents = snd_pcm_direct_poll_revents,
};
--- a/src/pcm/pcm_dsnoop.c
+++ b/src/pcm/pcm_dsnoop.c
@@ -208,17 +208,22 @@ static int snd_pcm_dsnoop_status(snd_pcm
static snd_pcm_state_t snd_pcm_dsnoop_state(snd_pcm_t *pcm)
{
snd_pcm_direct_t *dsnoop = pcm->private_data;
+ int err;
snd_pcm_state_t state;
state = snd_pcm_state(dsnoop->spcm);
switch (state) {
- case SND_PCM_STATE_XRUN:
case SND_PCM_STATE_SUSPENDED:
case SND_PCM_STATE_DISCONNECTED:
dsnoop->state = state;
return state;
+ case SND_PCM_STATE_XRUN:
+ if ((err = snd_pcm_direct_slave_recover(dsnoop)) < 0)
+ return err;
+ break;
default:
break;
}
+ snd_pcm_direct_client_chk_xrun(dsnoop, pcm);
return dsnoop->state;
}
@@ -531,7 +536,7 @@ static const snd_pcm_fast_ops_t snd_pcm_
.avail_update = snd_pcm_dsnoop_avail_update,
.mmap_commit = snd_pcm_dsnoop_mmap_commit,
.htimestamp = snd_pcm_dsnoop_htimestamp,
- .poll_descriptors = NULL,
+ .poll_descriptors = snd_pcm_direct_poll_descriptors,
.poll_descriptors_count = NULL,
.poll_revents = snd_pcm_direct_poll_revents,
};

View File

@ -0,0 +1,51 @@
From 79a358ae26f74ed9b92b2190d4725325edf0c787 Mon Sep 17 00:00:00 2001
From: Andreas Pape <apape@de.adit-jv.com>
Date: Tue, 10 Jan 2017 12:04:09 +0530
Subject: [PATCH 13/43] pcm: direct: don't return bogus buffer levels in xrun
state
Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
Signed-off-by: Mounesh Sutar <mounesh_sutar@mentor.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_dmix.c | 3 +++
src/pcm/pcm_dshare.c | 3 +++
src/pcm/pcm_dsnoop.c | 3 +++
3 files changed, 9 insertions(+)
--- a/src/pcm/pcm_dmix.c
+++ b/src/pcm/pcm_dmix.c
@@ -882,6 +882,9 @@ static snd_pcm_sframes_t snd_pcm_dmix_av
if ((err = snd_pcm_dmix_sync_ptr(pcm)) < 0)
return err;
}
+ if (dmix->state == SND_PCM_STATE_XRUN)
+ return -EPIPE;
+
return snd_pcm_mmap_playback_avail(pcm);
}
--- a/src/pcm/pcm_dshare.c
+++ b/src/pcm/pcm_dshare.c
@@ -570,6 +570,9 @@ static snd_pcm_sframes_t snd_pcm_dshare_
if ((err = snd_pcm_dshare_sync_ptr(pcm)) < 0)
return err;
}
+ if (dshare->state == SND_PCM_STATE_XRUN)
+ return -EPIPE;
+
return snd_pcm_mmap_playback_avail(pcm);
}
--- a/src/pcm/pcm_dsnoop.c
+++ b/src/pcm/pcm_dsnoop.c
@@ -454,6 +454,9 @@ static snd_pcm_sframes_t snd_pcm_dsnoop_
if (err < 0)
return err;
}
+ if (dsnoop->state == SND_PCM_STATE_XRUN)
+ return -EPIPE;
+
return snd_pcm_mmap_capture_avail(pcm);
}

View File

@ -0,0 +1,284 @@
From 360c976aaa051809c34cb412ffa52380baeaabee Mon Sep 17 00:00:00 2001
From: Vinod Koul <vinod.koul@intel.com>
Date: Thu, 12 Jan 2017 14:50:28 +0530
Subject: [PATCH 14/43] conf/ucm: broxton: add broxton-rt298 conf files
This adds the UCM conf files for broxton enabling with rt298 codec on
I2S audio, HDMI and DMIC ports.
Signed-off-by: Nishit Sharma <nishitx.sharma@intel.com>
Signed-off-by: G Kranthi <gudishax.kranthikumar@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
configure.ac | 1
src/conf/ucm/Makefile.am | 2
src/conf/ucm/broxton-rt298/Hdmi1 | 22 ++++
src/conf/ucm/broxton-rt298/Hdmi2 | 14 ++
src/conf/ucm/broxton-rt298/HiFi | 129 ++++++++++++++++++++++++++
src/conf/ucm/broxton-rt298/Makefile.am | 4
src/conf/ucm/broxton-rt298/broxton-rt298.conf | 58 +++++++++++
7 files changed, 229 insertions(+), 1 deletion(-)
create mode 100644 src/conf/ucm/broxton-rt298/Hdmi1
create mode 100644 src/conf/ucm/broxton-rt298/Hdmi2
create mode 100644 src/conf/ucm/broxton-rt298/HiFi
create mode 100644 src/conf/ucm/broxton-rt298/Makefile.am
create mode 100644 src/conf/ucm/broxton-rt298/broxton-rt298.conf
--- a/configure.ac
+++ b/configure.ac
@@ -684,6 +684,7 @@ AC_OUTPUT(Makefile doc/Makefile doc/pict
src/conf/topology/bxtrt298/Makefile \
alsalisp/Makefile aserver/Makefile \
test/Makefile test/lsb/Makefile \
+ src/conf/ucm/broxton-rt298/Makefile \
utils/Makefile utils/alsa-lib.spec utils/alsa.pc)
dnl Create asoundlib.h dynamically according to configure options
--- a/src/conf/ucm/Makefile.am
+++ b/src/conf/ucm/Makefile.am
@@ -1 +1 @@
-SUBDIRS=DAISY-I2S PandaBoard PandaBoardES SDP4430 tegraalc5632 PAZ00 GoogleNyan broadwell-rt286 skylake-rt286 VEYRON-I2S chtrt5645 DB410c
+SUBDIRS=DAISY-I2S PandaBoard PandaBoardES SDP4430 tegraalc5632 PAZ00 GoogleNyan broadwell-rt286 skylake-rt286 VEYRON-I2S chtrt5645 DB410c broxton-rt298
--- /dev/null
+++ b/src/conf/ucm/broxton-rt298/Hdmi1
@@ -0,0 +1,22 @@
+# Usecase for device HDMI1/Display Port stereo playback on Intel SKYLAKE/KABYLAKE platforms
+# For Audio in I2S mode
+
+SectionDevice."Hdmi1" {
+ Comment "HDMI/Display Port 1 Stereo"
+
+ EnableSequence [
+ exec "echo Hdmi1 EnableSequnece"
+ ]
+
+ DisableSequence [
+ exec "echo Hdmi1 DisableSequnece"
+ ]
+
+ Value {
+ PlaybackPCM "hw:broxtonrt298,4"
+ PlaybackChannels "2"
+ PlaybackPriority "3"
+ JackControl "HDMI/DP, pcm=4 Jack"
+ }
+}
+
--- /dev/null
+++ b/src/conf/ucm/broxton-rt298/Hdmi2
@@ -0,0 +1,14 @@
+# Usecase for device HDMI2/Display Port stereo playback on Intel Broxton platforms
+# For Audio in I2S mode
+
+SectionDevice."Hdmi2" {
+ Comment "HDMI/Display Port 2 Stereo"
+
+ Value {
+ PlaybackPCM "hw:broxtonrt298,5"
+ PlaybackChannels "2"
+ PlaybackPriority "4"
+ JackControl "HDMI/DP, pcm=5 Jack"
+ }
+}
+
--- /dev/null
+++ b/src/conf/ucm/broxton-rt298/HiFi
@@ -0,0 +1,129 @@
+# Usecase for stereo playback Speaker and Headset, Recording on DMIC and Headset MIC.
+# For Audio in I2S mode on Intel Broxton platforms
+
+SectionVerb {
+
+ EnableSequence [
+ cdev "hw:broxtonrt298"
+ cset "name='media0_out mo dmic01_hifi_in mi Switch' 1"
+ ]
+
+ DisableSequence [
+ cdev "hw:broxtonrt298"
+ ]
+
+ Value {
+ TQ "HiFi"
+ CapturePCM "hw:broxtonrt298,1"
+ PlaybackPCM "hw:broxtonrt298,0"
+ }
+}
+
+SectionDevice."dmiccap" {
+ Comment "DMIC Stereo"
+
+ ConflictingDevice [
+ "Headset"
+ ]
+
+ EnableSequence [
+
+ cdev "hw:broxtonrt298"
+ exec "echo broxtonrt298 dmiccap called"
+ cset "name='media0_out mo dmic01_hifi_in mi Switch' 1"
+ cset "name='media0_out mo codec0_in mi Switch' 0"
+ cset "name='Mic Jack Switch' 0"
+
+ ]
+
+ DisableSequence [
+ cdev "hw:broxtonrt298"
+ cset "name='media0_out mo codec0_in mi Switch' 1"
+ cset "name='media0_out mo dmic01_hifi_in mi Switch' 0"
+ cset "name='Mic Jack Switch' 1"
+ cset "name='ADC 0 Mux' 0"
+ ]
+ Value {
+ CaptureChannels "2"
+ CapturePriority "2"
+ }
+}
+
+SectionDevice."Headphones" {
+ Comment "Headphones"
+
+ ConflictingDevice [
+ "Speaker"
+ ]
+ EnableSequence [
+ cdev "hw:broxtonrt298"
+ exec "echo broxtonrt298 Headphone called"
+ cset "name='HPO L Switch' 1"
+ cset "name='HPO R Switch' 1"
+ cset "name='Headphone Jack Switch' 1"
+ cset "name='Speaker Playback Switch' 0,0"
+ ]
+
+ DisableSequence [
+ cdev "hw:broxtonrt298"
+ ]
+ Value {
+ PlaybackChannels "2"
+ PlaybackPriority "1"
+ JackControl "Headphone Jack"
+ JackHWMute "Speaker"
+ }
+}
+
+SectionDevice."Speaker" {
+ Comment "Speaker"
+
+ ConflictingDevice [
+ "Headphones"
+ ]
+ EnableSequence [
+ cdev "hw:broxtonrt298"
+ exec "echo broxtonrt298 speaker called"
+ cset "name='SPO Switch' 1"
+ cset "name='Speaker Playback Switch' 1,1"
+ cset "name='Speaker Switch' 1"
+ cset "name='HPO L Switch' 0"
+ cset "name='HPO R Switch' 0"
+ ]
+
+ DisableSequence [
+ ]
+ Value {
+ PlaybackChannels "2"
+ PlaybackPriority "1"
+ JackHWMute "Headphones"
+ }
+}
+
+SectionDevice."Headset" {
+ Comment "Headset Mic"
+
+ ConflictingDevice [
+ "dmiccap"
+ ]
+ EnableSequence [
+ cdev "hw:broxtonrt298"
+ exec "echo broxtonrt298 Headset called"
+ cset "name='media0_out mo codec0_in mi Switch' 1"
+ cset "name='ADC0 Capture Volume' 105,105"
+ cset "name='ADC 0 Mux' 0"
+ cset "name='Mic Jack Switch' 1"
+ cset "name='media0_out mo dmic01_hifi_in mi Switch' 0"
+ ]
+
+ DisableSequence [
+ cdev "hw:broxtonrt298"
+ cset "name='media0_out mo dmic01_hifi_in mi Switch' 1"
+ cset "name='media0_out mo codec0_in mi Switch' 0"
+ ]
+ Value {
+ CaptureChannels "2"
+ CapturePriority "2"
+ JackControl "Mic Jack"
+ }
+}
--- /dev/null
+++ b/src/conf/ucm/broxton-rt298/Makefile.am
@@ -0,0 +1,4 @@
+alsaconfigdir = @ALSA_CONFIG_DIR@
+ucmdir = $(alsaconfigdir)/ucm/broxton-rt298
+ucm_DATA = broxton-rt298.conf HiFi Hdmi1 Hdmi2
+EXTRA_DIST = $(ucm_DATA)
--- /dev/null
+++ b/src/conf/ucm/broxton-rt298/broxton-rt298.conf
@@ -0,0 +1,58 @@
+# UCM for Intel Broxton platforms
+# For Audio in I2S mode
+
+SectionUseCase."HiFi" {
+ File "HiFi"
+ Comment "Play and record HiFi quality Music"
+}
+
+SectionUseCase."Hdmi1" {
+ File "Hdmi1"
+ Comment "Play on Hdmi/DP 1"
+}
+
+SectionUseCase."Hdmi2" {
+ File "Hdmi2"
+ Comment "Play on Hdmi/DP 2"
+}
+
+ValueDefaults {
+ PlaybackCTL "hw:broxtonrt298"
+ CaptureCTL "hw:broxtonrt298"
+ CaptureChannels "2"
+ CapturePriority "2"
+}
+
+SectionDefaults [
+ cdev "hw:broxtonrt298"
+ exec "echo broxtonrt298 CONF Defaults"
+ cset "name='Headphone Jack Switch' 1"
+ cset "name='Speaker Switch' 1"
+ cset "name='Speaker Playback Switch' 0,0"
+ cset "name='Front DAC Switch' 1"
+ cset "name='Front RECMIX Switch' 0"
+ cset "name='Mic Jack Switch' 1"
+ cset "name='ADC 0 Mux' 2"
+ cset "name='ADC 1 Mux' 0"
+ cset "name='DAC0 Playback Volume' 100,100"
+ cset "name='HPO L Switch' 0"
+ cset "name='HPO Mux' 0"
+ cset "name='HPO R Switch' 0"
+ cset "name='Pin 5 Mux' 1"
+ cset "name='Pin 6 Mux' 2"
+ cset "name='Pin 7 Mux' 3"
+ cset "name='RECMIX Beep Switch' 0"
+ cset "name='RECMIX Line1 Switch' 0"
+ cset "name='RECMIX Mic1 Switch' 0"
+ cset "name='SPK Mux' 0"
+ cset "name='SPO Switch' 1"
+ cset "name='codec0_out mo codec0_in mi Switch' 0"
+ cset "name='codec0_out mo dmic01_hifi_in mi Switch' 0"
+ cset "name='codec0_out mo media0_in mi Switch' 1"
+ cset "name='codec1_out mo codec0_in mi Switch' 0"
+ cset "name='codec1_out mo dmic01_hifi_in mi Switch' 0"
+ cset "name='codec1_out mo media0_in mi Switch' 0"
+ cset "name='media0_out mo codec0_in mi Switch' 1"
+ cset "name='media0_out mo dmic01_hifi_in mi Switch' 1"
+ cset "name='media0_out mo media0_in mi Switch' 0"
+]

View File

@ -0,0 +1,32 @@
From 24e63b75275e9c923c336b8dba3919b980e8f234 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 16 Jan 2017 16:21:52 +0100
Subject: [PATCH 15/43] pcm: direct: Fix deadlock in poll_descriptors
The recent change in PCM direct plugins to check XRUN in
poll_descriptors callback caused a regression; as consequence, the
whole playback hangs up.
The culprit is a mutex dead lock by the call in snd_pcm_state() inside
the new snd_pcm_direct_poll_descriptors(). The poll_descriptors code
path is protected with pcm mutex, thus an unlocked version
(__snd_pcm_state()) has to be used inside the callback instead.
Fixes: 789ee39727a1 ("pcm: direct: check state before enter poll on timer")
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_direct.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/src/pcm/pcm_direct.c
+++ b/src/pcm/pcm_direct.c
@@ -676,7 +676,8 @@ int snd_pcm_direct_poll_descriptors(snd_
}
/* this will also evaluate slave state and enter xrun if necessary */
- switch (snd_pcm_state(pcm)) {
+ /* using __snd_pcm_state() since this function is called inside lock */
+ switch (__snd_pcm_state(pcm)) {
case SND_PCM_STATE_XRUN:
return -EPIPE;
default:

View File

@ -0,0 +1,43 @@
From 2b9b3f013467765219c8ab8a50943d3c7db68f75 Mon Sep 17 00:00:00 2001
From: Mengdong Lin <mengdong.lin@linux.intel.com>
Date: Wed, 18 Jan 2017 11:52:35 +0800
Subject: [PATCH 16/43] ucm: Assure the user input card name not to exceed max
size of card long name
Users can load a card's UCM configuration file by giving the card short
name or long name, which should not exceed the maximum card long name
defined by the kernel. The kernel uses an 80-character buffer to store
the card long name.
Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/ucm/parser.c | 6 ++++++
src/ucm/ucm_local.h | 1 +
2 files changed, 7 insertions(+)
--- a/src/ucm/parser.c
+++ b/src/ucm/parser.c
@@ -1335,6 +1335,12 @@ static int load_master_config(const char
char *env = getenv(ALSA_CONFIG_UCM_VAR);
int err;
+ if (strnlen(card_name, MAX_CARD_LONG_NAME) == MAX_CARD_LONG_NAME) {
+ uc_error("error: invalid card name %s (at most %d chars)\n",
+ card_name, MAX_CARD_LONG_NAME - 1);
+ return -EINVAL;
+ }
+
snprintf(filename, sizeof(filename)-1,
"%s/%s/%s.conf", env ? env : ALSA_USE_CASE_DIR,
card_name, card_name);
--- a/src/ucm/ucm_local.h
+++ b/src/ucm/ucm_local.h
@@ -41,6 +41,7 @@
#include "use-case.h"
#define MAX_FILE 256
+#define MAX_CARD_LONG_NAME 80
#define ALSA_USE_CASE_DIR ALSA_CONFIG_DIR "/ucm"
#define SEQUENCE_ELEMENT_TYPE_CDEV 1

View File

@ -0,0 +1,177 @@
From 4b9297e65f541f1a6c1b4a036f66936b9cafe030 Mon Sep 17 00:00:00 2001
From: Mengdong Lin <mengdong.lin@linux.intel.com>
Date: Wed, 18 Jan 2017 11:53:35 +0800
Subject: [PATCH 17/43] ucm: Load device-specific configuration file based on
the card long name
Intel DSP platform drivers are used by many different devices. For user
space to differentiate them, ASoC machine drivers may use the DMI info
(vendor-product-version-board) as card long name. Possible card long names
are:
DellInc.-XPS139343-01-0310JH
ASUSTeKCOMPUTERINC.-T100TA-1.0-T100TA
Circuitco-MinnowboardMaxD0PLATFORM-D0-MinnowBoardMAX
...
If we want to define a device-specific UCM config file for a card, we
need to use the card long name as the name of both the directory that
contains the UCM config file and the UCM config file itself, like
longname/longname.conf
When being asked to load configuration file of a card, UCM will try to
find the card in the local machine and get its long name. If the card
long name is available, try to load the file longname/longname.conf to
get the best device-specific configuration; if this file is not available,
fall back to load the default configuration file shortname/shortname.conf
as before.
This update is backward compatible, because if ASoC machine drivers don't
explicity use DMI or other means to set the card long name, ASoC core
will use the card short name as the long name. And so UCM will load the
config file that matches both the card short name and the long name.
Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/ucm/parser.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++---
src/ucm/ucm_local.h | 2 +
2 files changed, 97 insertions(+), 4 deletions(-)
--- a/src/ucm/parser.c
+++ b/src/ucm/parser.c
@@ -56,6 +56,9 @@ static const char * const component_dir[
NULL, /* terminator */
};
+static int filename_filter(const struct dirent *dirent);
+static int is_component_directory(const char *dir);
+
static int parse_sequence(snd_use_case_mgr_t *uc_mgr,
struct list_head *base,
snd_config_t *cfg);
@@ -1329,6 +1332,66 @@ static int parse_master_file(snd_use_cas
return 0;
}
+/* find the card in the local machine and store the card long name */
+static int get_card_long_name(snd_use_case_mgr_t *mgr)
+{
+ const char *card_name = mgr->card_name;
+ snd_ctl_t *handle;
+ int card, err;
+ snd_ctl_card_info_t *info;
+ const char *_name, *_long_name;
+
+ snd_ctl_card_info_alloca(&info);
+
+ card = -1;
+ if (snd_card_next(&card) < 0 || card < 0) {
+ uc_error("no soundcards found...");
+ return -1;
+ }
+
+ while (card >= 0) {
+ char name[32];
+
+ sprintf(name, "hw:%d", card);
+ err = snd_ctl_open(&handle, name, 0);
+ if (err < 0) {
+ uc_error("control open (%i): %s", card,
+ snd_strerror(err));
+ goto next_card;
+ }
+
+ err = snd_ctl_card_info(handle, info);
+ if (err < 0) {
+ uc_error("control hardware info (%i): %s", card,
+ snd_strerror(err));
+ snd_ctl_close(handle);
+ goto next_card;
+ }
+
+ /* Find the local card by comparing the given name with the
+ * card short name and long name. The given card name may be
+ * either a short name or long name, because users may open
+ * the card by either of the two names.
+ */
+ _name = snd_ctl_card_info_get_name(info);
+ _long_name = snd_ctl_card_info_get_longname(info);
+ if (!strcmp(card_name, _name)
+ || !strcmp(card_name, _long_name)) {
+ strcpy(mgr->card_long_name, _long_name);
+ snd_ctl_close(handle);
+ return 0;
+ }
+
+ snd_ctl_close(handle);
+next_card:
+ if (snd_card_next(&card) < 0) {
+ uc_error("snd_card_next");
+ break;
+ }
+ }
+
+ return -1;
+}
static int load_master_config(const char *card_name, snd_config_t **cfg)
{
char filename[MAX_FILE];
@@ -1356,15 +1419,43 @@ static int load_master_config(const char
return 0;
}
-/* load master use case file for sound card */
+/* load master use case file for sound card
+ *
+ * The same ASoC machine driver can be shared by many different devices.
+ * For user space to differentiate them and get the best device-specific
+ * configuration, ASoC machine drivers may use the DMI info
+ * (vendor-product-version-board) as the card long name. And user space can
+ * define configuration files like longnamei/longname.conf for a specific device.
+ *
+ * This function will try to find the card in the local machine and get its
+ * long name, then load the file longname/longname.conf to get the best
+ * device-specific configuration. If the card is not found in the local
+ * machine or the device-specific file is not available, fall back to load
+ * the default configuration file name/name.conf.
+ */
int uc_mgr_import_master_config(snd_use_case_mgr_t *uc_mgr)
{
snd_config_t *cfg;
int err;
- err = load_master_config(uc_mgr->card_name, &cfg);
- if (err < 0)
- return err;
+ err = get_card_long_name(uc_mgr);
+ if (err == 0) /* load file that maches the card long name */
+ err = load_master_config(uc_mgr->card_long_name, &cfg);
+
+ if (err == 0) {
+ /* got device-specific file that matches the card long name */
+ strcpy(uc_mgr->conf_file_name, uc_mgr->card_long_name);
+ } else {
+ /* Fall back to the file that maches the given card name,
+ * either short name or long name (users may open a card by
+ * its name or long name).
+ */
+ err = load_master_config(uc_mgr->card_name, &cfg);
+ if (err < 0)
+ return err;
+ strcpy(uc_mgr->conf_file_name, uc_mgr->card_name);
+ }
+
err = parse_master_file(uc_mgr, cfg);
snd_config_delete(cfg);
if (err < 0)
--- a/src/ucm/ucm_local.h
+++ b/src/ucm/ucm_local.h
@@ -191,6 +191,8 @@ struct use_case_verb {
*/
struct snd_use_case_mgr {
char *card_name;
+ char card_long_name[MAX_CARD_LONG_NAME];
+ char conf_file_name[MAX_CARD_LONG_NAME];
char *comment;
/* use case verb, devices and modifier configs parsed from files */

View File

@ -0,0 +1,51 @@
From e93d93a8cd37f94f119aba72ca05d7f92b648bcc Mon Sep 17 00:00:00 2001
From: Mengdong Lin <mengdong.lin@linux.intel.com>
Date: Wed, 18 Jan 2017 11:53:42 +0800
Subject: [PATCH 18/43] ucm: Add command 'get _file' to get the config file
name of the opened card
After opening a card, this command can show the name of the actually
loaded configuration file, either matches the card name or card long name.
So developers can check if there is a device-sepcific configuration file
available for a given card.
Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/use-case.h | 1 +
src/ucm/main.c | 14 ++++++++++++++
2 files changed, 15 insertions(+)
--- a/include/use-case.h
+++ b/include/use-case.h
@@ -230,6 +230,7 @@ int snd_use_case_get_list(snd_use_case_m
* Known identifiers:
* - NULL - return current card
* - _verb - return current verb
+ * - _file - return configuration file loaded for current card
*
* - [=]{NAME}[/[{modifier}|{/device}][/{verb}]]
* - value identifier {NAME}
--- a/src/ucm/main.c
+++ b/src/ucm/main.c
@@ -1528,6 +1528,20 @@ int snd_use_case_get(snd_use_case_mgr_t
goto __end;
}
err = 0;
+ } else if (strcmp(identifier, "_file") == 0) {
+ /* get the conf file name of the opened card */
+ if ((uc_mgr->card_name == NULL)
+ || (uc_mgr->conf_file_name[0] == '\0')) {
+ err = -ENOENT;
+ goto __end;
+ }
+ *value = strndup(uc_mgr->conf_file_name, MAX_FILE);
+ if (*value == NULL) {
+ err = -ENOMEM;
+ goto __end;
+ }
+ err = 0;
+
} else if (identifier[0] == '_') {
err = -ENOENT;
goto __end;

View File

@ -0,0 +1,278 @@
From ec40aafa4374f2388876702513c4b3eee2e2235f Mon Sep 17 00:00:00 2001
From: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Date: Tue, 24 Jan 2017 14:59:08 +0000
Subject: [PATCH 19/43] topology: Fix incorrect license in source comments.
The topology source files had the wrong licence specified in the
comments when initially upstreamed. The topology source files are all
licensed under the LGPL-2.1 and not the GPLv2.
All earlier versions of the alsa-lib topology source files must be
considered LGPL-2.1 like the other source files in alsa-lib and also
as specified in the alsa-lib COPYING file.
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/topology/builder.c | 15 ++++++++-------
src/topology/channel.c | 15 ++++++++-------
src/topology/ctl.c | 15 ++++++++-------
src/topology/dapm.c | 15 ++++++++-------
src/topology/data.c | 15 ++++++++-------
src/topology/elem.c | 15 ++++++++-------
src/topology/ops.c | 15 ++++++++-------
src/topology/parser.c | 15 ++++++++-------
src/topology/pcm.c | 15 ++++++++-------
src/topology/text.c | 15 ++++++++-------
10 files changed, 80 insertions(+), 70 deletions(-)
--- a/src/topology/builder.c
+++ b/src/topology/builder.c
@@ -2,14 +2,15 @@
Copyright(c) 2014-2015 Intel Corporation
All rights reserved.
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as
- published by the Free Software Foundation.
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
Authors: Mengdong Lin <mengdong.lin@intel.com>
Yao Jin <yao.jin@intel.com>
--- a/src/topology/channel.c
+++ b/src/topology/channel.c
@@ -2,14 +2,15 @@
Copyright(c) 2014-2015 Intel Corporation
All rights reserved.
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as
- published by the Free Software Foundation.
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
Authors: Mengdong Lin <mengdong.lin@intel.com>
Yao Jin <yao.jin@intel.com>
--- a/src/topology/ctl.c
+++ b/src/topology/ctl.c
@@ -2,14 +2,15 @@
Copyright(c) 2014-2015 Intel Corporation
All rights reserved.
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as
- published by the Free Software Foundation.
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
Authors: Mengdong Lin <mengdong.lin@intel.com>
Yao Jin <yao.jin@intel.com>
--- a/src/topology/dapm.c
+++ b/src/topology/dapm.c
@@ -2,14 +2,15 @@
Copyright(c) 2014-2015 Intel Corporation
All rights reserved.
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as
- published by the Free Software Foundation.
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
Authors: Mengdong Lin <mengdong.lin@intel.com>
Yao Jin <yao.jin@intel.com>
--- a/src/topology/data.c
+++ b/src/topology/data.c
@@ -2,14 +2,15 @@
Copyright(c) 2014-2015 Intel Corporation
All rights reserved.
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as
- published by the Free Software Foundation.
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
Authors: Mengdong Lin <mengdong.lin@intel.com>
Yao Jin <yao.jin@intel.com>
--- a/src/topology/elem.c
+++ b/src/topology/elem.c
@@ -2,14 +2,15 @@
Copyright(c) 2014-2015 Intel Corporation
All rights reserved.
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as
- published by the Free Software Foundation.
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
Authors: Mengdong Lin <mengdong.lin@intel.com>
Yao Jin <yao.jin@intel.com>
--- a/src/topology/ops.c
+++ b/src/topology/ops.c
@@ -2,14 +2,15 @@
Copyright(c) 2014-2015 Intel Corporation
All rights reserved.
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as
- published by the Free Software Foundation.
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
Authors: Mengdong Lin <mengdong.lin@intel.com>
Yao Jin <yao.jin@intel.com>
--- a/src/topology/parser.c
+++ b/src/topology/parser.c
@@ -2,14 +2,15 @@
Copyright(c) 2014-2015 Intel Corporation
All rights reserved.
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as
- published by the Free Software Foundation.
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
Authors: Mengdong Lin <mengdong.lin@intel.com>
Yao Jin <yao.jin@intel.com>
--- a/src/topology/pcm.c
+++ b/src/topology/pcm.c
@@ -2,14 +2,15 @@
Copyright(c) 2014-2015 Intel Corporation
All rights reserved.
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as
- published by the Free Software Foundation.
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
Authors: Mengdong Lin <mengdong.lin@intel.com>
Yao Jin <yao.jin@intel.com>
--- a/src/topology/text.c
+++ b/src/topology/text.c
@@ -2,14 +2,15 @@
Copyright(c) 2014-2015 Intel Corporation
All rights reserved.
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as
- published by the Free Software Foundation.
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
Authors: Mengdong Lin <mengdong.lin@intel.com>
Yao Jin <yao.jin@intel.com>

View File

@ -0,0 +1,100 @@
From 4dfa8f08fb834f7b087f35f9ba1746cd0c989d02 Mon Sep 17 00:00:00 2001
From: Manohar Narkhede <Manohar.Narkhede@imgtec.com>
Date: Wed, 25 Jan 2017 22:14:15 +0100
Subject: [PATCH 20/43] conf/cards: add support for pistachio-card.
The data sheet of the chip and technical reference manual can be found at https://docs.creatordev.io/ci40/guides/hardwaredocs/cXT200_datasheet2.pdf
and https://docs.creatordev.io/ci40/guides/hardwaredocs/MIPS_Creator_cXT200_Technical_Reference_Manual_1.0.112.pdf.
The additional information about the cards can be found in src/conf/cards/pistachio-card.conf file.
Signed-off-by: Manohar Narkhede <Manohar.Narkhede@imgtec.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/conf/cards/Makefile.am | 1
src/conf/cards/aliases.conf | 1
src/conf/cards/pistachio-card.conf | 58 +++++++++++++++++++++++++++++++++++++
3 files changed, 60 insertions(+)
create mode 100644 src/conf/cards/pistachio-card.conf
--- a/src/conf/cards/Makefile.am
+++ b/src/conf/cards/Makefile.am
@@ -39,6 +39,7 @@ cfg_files = aliases.conf \
Maestro3.conf \
NFORCE.conf \
PC-Speaker.conf \
+ pistachio-card.conf \
PMac.conf \
PMacToonie.conf \
PS3.conf \
--- a/src/conf/cards/aliases.conf
+++ b/src/conf/cards/aliases.conf
@@ -55,6 +55,7 @@ AV100 cards.CMI8788
AV200 cards.CMI8788
CMI8786 cards.CMI8788
CMI8787 cards.CMI8788
+pistachio cards.pistachio-card
<confdir:pcm/default.conf>
<confdir:pcm/dmix.conf>
--- /dev/null
+++ b/src/conf/cards/pistachio-card.conf
@@ -0,0 +1,58 @@
+#
+# Configuration for the pistachio chip.
+#
+# The data sheet of the chip and technical reference manual can be
+found at
+https://docs.creatordev.io/ci40/guides/hardwaredocs/cXT200_datasheet2.p
+df # and
+https://docs.creatordev.io/ci40/guides/hardwaredocs/MIPS_Creator_cXT200_Technical_Reference_Manual_1.0.112.pdf.
+#
+# The list of hardware devices is as per below:
+#
+# root@OpenWrt:/# arecord -l
+# **** List of CAPTURE Hardware Devices **** card 0: pistachiocard [pistachio-card], device 1: pistachio-spdif-in snd-soc-dummy-dai-1 []
+# Subdevices: 1/1
+# Subdevice #0: subdevice #0
+# card 0: pistachiocard [pistachio-card], device 4: pistachio-i2s-in-0 snd-soc-dummy-dai-4 []
+# Subdevices: 1/1
+# Subdevice #0: subdevice #0
+#
+# root@OpenWrt:/# aplay -l
+# **** List of PLAYBACK Hardware Devices **** card 0: pistachiocard [pistachio-card], device 0: pistachio-spdif-out snd-soc-dummy-dai-0 []
+# Subdevices: 1/1
+# Subdevice #0: subdevice #0
+# card 0: pistachiocard [pistachio-card], device 2: pistachio-parallel-out pistachio_internal_dac-2 []
+# Subdevices: 1/1
+# Subdevice #0: subdevice #0
+# card 0: pistachiocard [pistachio-card], device 3: pistachio-i2s-out snd-soc-dummy-dai-3 []
+# Subdevices: 1/1
+# Subdevice #0: subdevice #0
+#
+
+pistachio-card.pcm.default{
+ @args [ CARD ]
+ @args.CARD {
+ type string
+ default "pistachio"
+ }
+ @args.DEVICE {
+ type integer
+ default 2
+ }
+
+ type asym
+ capture.pcm {
+ type multi
+ slaves.a.pcm "hw:0,4"
+ slaves.a.channels 12
+ bindings.0.slave a
+ bindings.0.channel 4
+ bindings.1.slave a
+ bindings.1.channel 5
+ }
+
+ playback.pcm {
+ type hw
+ card $CARD
+ device $DEVICE
+

View File

@ -0,0 +1,44 @@
From e1143dd9ba350eb19d13d4e298eeb55179712a1e Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 27 Jan 2017 12:01:51 +0100
Subject: [PATCH 21/43] pcm: multi: Drop the fixed slave_map[] in
snd_pcm_multi_open()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
slave_map[] in snd_pcm_multi_open() is a fixed size array and
obviously we have no overflow check, and eventually the program gets
an error when more than 64 channels are used.
Although we can modify the code to allocate the array dynamically, it
turned out that we can drop the whole slave_map[] thingy in this
function when looking at the code closely. In the past, it was used
to identify the one-to-many mapping. But the check was dropped, and
now it's nothing more than a sanity check.
Reported-by: Jörg Müller <joerg.mueller7744@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_multi.c | 3 ---
1 file changed, 3 deletions(-)
--- a/src/pcm/pcm_multi.c
+++ b/src/pcm/pcm_multi.c
@@ -1015,7 +1015,6 @@ int snd_pcm_multi_open(snd_pcm_t **pcmp,
snd_pcm_multi_t *multi;
unsigned int i;
snd_pcm_stream_t stream;
- char slave_map[64][64] = { { 0 } };
int err;
assert(pcmp);
@@ -1059,8 +1058,6 @@ int snd_pcm_multi_open(snd_pcm_t **pcmp,
bind->slave_channel = schannels[i];
if (sidxs[i] < 0)
continue;
- assert(!slave_map[sidxs[i]][schannels[i]]);
- slave_map[sidxs[i]][schannels[i]] = 1;
}
multi->channels_count = channels_count;

View File

@ -0,0 +1,115 @@
From 53dc36f1f465e2a1f9ed37906a7f16a438f941e4 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 7 Feb 2017 14:25:17 +0100
Subject: [PATCH 22/43] conf: Add card config for Intel HDMI/DP LPE audio
It's a playback-only device with a single PCM dedicated for HDMI/DP
output. The dmix is working with the latest driver code, so enable it
for default, while providing the hdmi PCM dev for the accesses with
AES bits.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/conf/cards/HdmiLpeAudio.conf | 85 +++++++++++++++++++++++++++++++++++++++
src/conf/cards/Makefile.am | 1
2 files changed, 86 insertions(+)
create mode 100644 src/conf/cards/HdmiLpeAudio.conf
--- /dev/null
+++ b/src/conf/cards/HdmiLpeAudio.conf
@@ -0,0 +1,85 @@
+#
+# Configuration for the Intel HDMI/DP LPE audio
+#
+
+<confdir:pcm/front.conf>
+
+HdmiLpeAudio.pcm.front.0 {
+ @args [ CARD ]
+ @args.CARD {
+ type string
+ }
+ type softvol
+ slave.pcm {
+ type hw
+ card $CARD
+ }
+ control {
+ name "PCM Playback Volume"
+ card $CARD
+ }
+}
+
+# default with dmix+softvol
+HdmiLpeAudio.pcm.default {
+ @args [ CARD ]
+ @args.CARD {
+ type string
+ }
+ type plug
+ slave.pcm {
+ type softvol
+ slave.pcm {
+ @func concat
+ strings [ "dmix:" $CARD ]
+ }
+ control {
+ name "PCM Playback Volume"
+ card $CARD
+ }
+ }
+}
+
+<confdir:pcm/surround40.conf>
+<confdir:pcm/surround21.conf>
+<confdir:pcm/surround41.conf>
+<confdir:pcm/surround50.conf>
+<confdir:pcm/surround51.conf>
+
+<confdir:pcm/hdmi.conf>
+
+HdmiLpeAudio.pcm.hdmi.0 {
+ @args [ CARD AES0 AES1 AES2 AES3 ]
+ @args.CARD {
+ type string
+ }
+ @args.AES0 {
+ type integer
+ }
+ @args.AES1 {
+ type integer
+ }
+ @args.AES2 {
+ type integer
+ }
+ @args.AES3 {
+ type integer
+ }
+ type hooks
+ slave.pcm {
+ type hw
+ card $CARD
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ {
+ interface PCM
+ name "IEC958 Playback Default"
+ lock true
+ preserve true
+ value [ $AES0 $AES1 $AES2 $AES3 ]
+ }
+ ]
+ }
+}
--- a/src/conf/cards/Makefile.am
+++ b/src/conf/cards/Makefile.am
@@ -30,6 +30,7 @@ cfg_files = aliases.conf \
FireWave.conf \
GUS.conf \
HDA-Intel.conf \
+ HdmiLpeAudio.conf \
ICE1712.conf \
ICE1724.conf \
ICH.conf \

View File

@ -0,0 +1,43 @@
From b5a2c06f6c5d69fc71ef648af95a044ee1dc25d0 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 9 Feb 2017 17:23:22 +0100
Subject: [PATCH 23/43] pcm: Avoid lock for snd_pcm_nonblock()
snd_pcm_nonblock() is called as snd_pcm_abort(). Since
snd_pcm_abort() is called often from a signal handler to clean things
up (e.g. aplay does it), we may face a deadlock if the signal is
raised during the locked operation.
There can be some way to check the deadlock state, but they would cost
much. Since the race condition of snd_pcm_nonblock() is quite small,
let's just drop the locking inside snd_pcm_nonblock() as a
workaround.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -759,7 +759,10 @@ int snd_pcm_nonblock(snd_pcm_t *pcm, int
int err = 0;
assert(pcm);
- __snd_pcm_lock(pcm); /* forced lock due to pcm field change */
+ /* FIXME: __snd_pcm_lock() call below is commented out because of the
+ * the possible deadlock in signal handler calling snd_pcm_abort()
+ */
+ /* __snd_pcm_lock(pcm); */ /* forced lock due to pcm field change */
if ((err = pcm->ops->nonblock(pcm->op_arg, nonblock)) < 0)
goto unlock;
if (nonblock == 2) {
@@ -775,7 +778,7 @@ int snd_pcm_nonblock(snd_pcm_t *pcm, int
pcm->mode &= ~SND_PCM_NONBLOCK;
}
unlock:
- __snd_pcm_unlock(pcm);
+ /* __snd_pcm_unlock(pcm); */ /* FIXME: see above */
return err;
}

View File

@ -0,0 +1,41 @@
From e31a3273df6eb619e35d10bf6a0fc0fded91d559 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 9 Feb 2017 17:29:21 +0100
Subject: [PATCH 24/43] pcm: Disable locking in async mode
When PCM is operated in async mode and an async handler calls some PCM
functions with lock during other PCM operations, we may hit a
deadlock.
Although async mode is rarely used, it's still a possible use case.
Disable the locking when the stream is opened in async mode or it's
set to async mode via snd_pcm_async().
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -799,6 +799,8 @@ int snd_pcm_async(snd_pcm_t *pcm, int si
sig = SIGIO;
if (pid == 0)
pid = getpid();
+ /* async handler may lead to a deadlock; suppose no multi thread */
+ pcm->lock_enabled = 0;
return pcm->ops->async(pcm->op_arg, sig, pid);
}
#endif
@@ -2597,7 +2599,10 @@ int snd_pcm_new(snd_pcm_t **pcmp, snd_pc
* each plugin may suppress this in its open call
*/
pcm->need_lock = 1;
- {
+ if (mode & SND_PCM_ASYNC) {
+ /* async handler may lead to a deadlock; suppose no MT */
+ pcm->lock_enabled = 0;
+ } else {
/* set lock_enabled field depending on $LIBASOUND_THREAD_SAFE */
static int do_lock_enable = -1; /* uninitialized */

View File

@ -0,0 +1,152 @@
From 22eca6468b4aea47c783770ec0739d1e13bf3bfc Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 10 Feb 2017 12:16:12 +0100
Subject: [PATCH 25/43] pcm: dmix: Allow disabling x86 optimizations
The dmix plugin has some optimized implementations for x86 using the
direct memory accesses, which was rather the original version, in
addition to the "generic" implementation using the semaphore
blocking. The x86 implementation relies on the memory coherency *and*
the fast read/write on it.
For other architectures, this has been always disabled just because of
memory coherency. But, the recent LPE audio development revealed
that, even on x86 platforms, the read/write performance might become
extremely bad when the buffer is marked as uncached. Some drivers
already know the buffer is uncached, we need to switch to the generic
mode in such a case.
This patch introduces yet another flag to dmix configuration,
direct_memory_access, that indicates whether the x86-specific
optimization can be used or not. Each driver can set the flag in its
cards config namespace, and the default dmix config refers to it.
As of this patch, only HDMI LPE Audio driver sets it.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/conf/cards/HdmiLpeAudio.conf | 3 +++
src/conf/pcm/dmix.conf | 15 +++++++++++++++
src/pcm/pcm_direct.c | 8 ++++++++
src/pcm/pcm_direct.h | 2 ++
src/pcm/pcm_dmix.c | 1 +
src/pcm/pcm_dmix_i386.c | 5 +++++
src/pcm/pcm_dmix_x86_64.c | 5 +++++
7 files changed, 39 insertions(+)
--- a/src/conf/cards/HdmiLpeAudio.conf
+++ b/src/conf/cards/HdmiLpeAudio.conf
@@ -20,6 +20,9 @@ HdmiLpeAudio.pcm.front.0 {
}
}
+# uncached memory reads have a high penalty
+HdmiLpeAudio.dmix.direct_memory_access false
+
# default with dmix+softvol
HdmiLpeAudio.pcm.default {
@args [ CARD ]
--- a/src/conf/pcm/dmix.conf
+++ b/src/conf/pcm/dmix.conf
@@ -49,6 +49,21 @@ pcm.!dmix {
@func refer
name defaults.pcm.ipc_perm
}
+ direct_memory_access {
+ @func refer
+ name {
+ @func concat
+ strings [
+ "cards."
+ {
+ @func card_driver
+ card $CARD
+ }
+ ".dmix.direct_memory_access"
+ ]
+ }
+ default true
+ }
slave {
pcm {
type hw
--- a/src/pcm/pcm_direct.c
+++ b/src/pcm/pcm_direct.c
@@ -1861,6 +1861,7 @@ int snd_pcm_direct_parse_open_conf(snd_c
rec->slowptr = 1;
rec->max_periods = 0;
rec->var_periodsize = 1;
+ rec->direct_memory_access = 1;
/* read defaults */
if (snd_config_search(root, "defaults.pcm.dmix_max_periods", &n) >= 0) {
@@ -1974,6 +1975,13 @@ int snd_pcm_direct_parse_open_conf(snd_c
rec->var_periodsize = err;
continue;
}
+ if (strcmp(id, "direct_memory_access") == 0) {
+ err = snd_config_get_bool(n);
+ if (err < 0)
+ return err;
+ rec->direct_memory_access = err;
+ continue;
+ }
SNDERR("Unknown field %s", id);
return -EINVAL;
}
--- a/src/pcm/pcm_direct.h
+++ b/src/pcm/pcm_direct.h
@@ -159,6 +159,7 @@ struct snd_pcm_direct {
unsigned int channels; /* client's channels */
unsigned int *bindings;
unsigned int recoveries; /* mirror of executed recoveries on slave */
+ int direct_memory_access; /* use arch-optimized buffer RW */
union {
struct {
int shmid_sum; /* IPC global sum ring buffer memory identification */
@@ -340,6 +341,7 @@ struct snd_pcm_direct_open_conf {
int slowptr;
int max_periods;
int var_periodsize;
+ int direct_memory_access;
snd_config_t *slave;
snd_config_t *bindings;
};
--- a/src/pcm/pcm_dmix.c
+++ b/src/pcm/pcm_dmix.c
@@ -1065,6 +1065,7 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp,
dmix->max_periods = opts->max_periods;
dmix->var_periodsize = opts->var_periodsize;
dmix->sync_ptr = snd_pcm_dmix_sync_ptr;
+ dmix->direct_memory_access = opts->direct_memory_access;
retry:
if (first_instance) {
--- a/src/pcm/pcm_dmix_i386.c
+++ b/src/pcm/pcm_dmix_i386.c
@@ -87,6 +87,11 @@ static void mix_select_callbacks(snd_pcm
{
static int smp = 0, mmx = 0, cmov = 0;
+ if (!dmix->direct_memory_access) {
+ generic_mix_select_callbacks(dmix);
+ return;
+ }
+
if (!((1ULL<< dmix->shmptr->s.format) & i386_dmix_supported_format)) {
generic_mix_select_callbacks(dmix);
return;
--- a/src/pcm/pcm_dmix_x86_64.c
+++ b/src/pcm/pcm_dmix_x86_64.c
@@ -70,6 +70,11 @@ static void mix_select_callbacks(snd_pcm
{
static int smp = 0;
+ if (!dmix->direct_memory_access) {
+ generic_mix_select_callbacks(dmix);
+ return;
+ }
+
if (!((1ULL<< dmix->shmptr->s.format) & x86_64_dmix_supported_format)) {
generic_mix_select_callbacks(dmix);
return;

View File

@ -0,0 +1,92 @@
From df7694d80cdd7d273b34ead6841b9f32f5991966 Mon Sep 17 00:00:00 2001
From: Timo Wischer <twischer@de.adit-jv.com>
Date: Fri, 17 Feb 2017 12:45:36 +0530
Subject: [PATCH 26/43] pcm: dmix_rewind corrupts application pointer fix
sometimes pulseaudio stops with the following assertion in libasound.so:
alsa-lib-1.0.29/src/pcm/pcm.c:2761:
snd_pcm_area_copy: Assertion `dst < src || dst >= src + bytes' failed.
Application pointer is handled properly, in cases of rewind operations.
Signed-off-by: Timo Wischer <twischer@de.adit-jv.com>
Signed-off-by: Ravikiran Polepalli <ravikiran_polepalli@mentor.com>
Signed-off-by: Mikhail Durnev <mikhail_durnev@mentor.com>
Signed-off-by: Mounesh Sutar <sutar.mounesh@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_dmix.c | 33 +++++++++++++++++++++++----------
1 file changed, 23 insertions(+), 10 deletions(-)
--- a/src/pcm/pcm_dmix.c
+++ b/src/pcm/pcm_dmix.c
@@ -706,7 +706,7 @@ static snd_pcm_sframes_t snd_pcm_dmix_re
{
snd_pcm_direct_t *dmix = pcm->private_data;
snd_pcm_uframes_t slave_appl_ptr, slave_size;
- snd_pcm_uframes_t appl_ptr, size, transfer, result;
+ snd_pcm_uframes_t appl_ptr, size, transfer, result, frames_to_remix;
int err;
const snd_pcm_channel_area_t *src_areas, *dst_areas;
@@ -717,6 +717,13 @@ static snd_pcm_sframes_t snd_pcm_dmix_re
return err;
}
+ /* (appl_ptr - last_appl_ptr) indicates the frames which are not
+ * already mixed
+ * (last_appl_ptr - hw_ptr) indicates the frames which are already
+ * mixed but not played yet.
+ * So they can be remixed.
+ */
+
if (dmix->last_appl_ptr < dmix->appl_ptr)
size = dmix->appl_ptr - dmix->last_appl_ptr;
else
@@ -729,6 +736,9 @@ static snd_pcm_sframes_t snd_pcm_dmix_re
return size;
result = size;
+ /* Always at this point last_appl_ptr == appl_ptr
+ * So (appl_ptr - hw_ptr) indicates the frames which can be remixed
+ */
if (dmix->hw_ptr < dmix->appl_ptr)
size = dmix->appl_ptr - dmix->hw_ptr;
else
@@ -741,9 +751,12 @@ static snd_pcm_sframes_t snd_pcm_dmix_re
slave_size = dmix->slave_appl_ptr + (pcm->boundary - dmix->slave_hw_ptr);
if (slave_size < size)
size = slave_size;
- frames -= size;
- result += size;
-
+
+ /* frames which should be remixed will be saved
+ * to also backward the appl pointer on success
+ */
+ frames_to_remix = size;
+
/* add sample areas here */
src_areas = snd_pcm_mmap_areas(pcm);
dst_areas = snd_pcm_mmap_areas(dmix->spcm);
@@ -769,15 +782,15 @@ static snd_pcm_sframes_t snd_pcm_dmix_re
appl_ptr += transfer;
appl_ptr %= pcm->buffer_size;
}
- dmix->last_appl_ptr -= frames;
- dmix->last_appl_ptr %= pcm->boundary;
- dmix->slave_appl_ptr -= frames;
- dmix->slave_appl_ptr %= dmix->slave_boundary;
dmix_up_sem(dmix);
- snd_pcm_mmap_appl_backward(pcm, frames);
+ snd_pcm_mmap_appl_backward(pcm, frames_to_remix);
+ result += frames_to_remix;
+ /* At this point last_appl_ptr and appl_ptr has to indicate the
+ * position of the first not mixed frame
+ */
- return result + frames;
+ return result;
}
static snd_pcm_sframes_t snd_pcm_dmix_forwardable(snd_pcm_t *pcm)

View File

@ -0,0 +1,97 @@
From 9219034301a3bf3d8de57ac5672bbc1c53f18049 Mon Sep 17 00:00:00 2001
From: Andreas Pape <apape@de.adit-jv.com>
Date: Fri, 17 Feb 2017 12:45:56 +0530
Subject: [PATCH 27/43] pcm: direct: fix race on clearing timer events
snd_timer handling is racy: plugins clear timer queue if avail_min
is not reached to force a sleep on timer. The race can happen if
the expected event arrives in between the avail check and the
clearing of pending events. If this race happens, the user will
unnecessarily wait for one more timer event. On low latency/realtime
streams this can lead to xruns and must be avoided.
As a fix we recheck avail after having cleared poll events.
Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
Signed-off-by: Mounesh Sutar <sutar.mounesh@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_direct.c | 23 +++++++++++++++++++----
src/pcm/pcm_direct.h | 2 +-
2 files changed, 20 insertions(+), 5 deletions(-)
--- a/src/pcm/pcm_direct.c
+++ b/src/pcm/pcm_direct.c
@@ -515,10 +515,12 @@ int snd_pcm_direct_async(snd_pcm_t *pcm,
}
/* empty the timer read queue */
-void snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix)
+int snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix)
{
+ int changed = 0;
if (dmix->timer_need_poll) {
while (poll(&dmix->timer_fd, 1, 0) > 0) {
+ changed++;
/* we don't need the value */
if (dmix->tread) {
snd_timer_tread_t rbuf[4];
@@ -533,15 +535,17 @@ void snd_pcm_direct_clear_timer_queue(sn
snd_timer_tread_t rbuf[4];
int len;
while ((len = snd_timer_read(dmix->timer, rbuf,
- sizeof(rbuf))) > 0 &&
+ sizeof(rbuf))) > 0
+ && (++changed) &&
len != sizeof(rbuf[0]))
;
} else {
snd_timer_read_t rbuf;
while (snd_timer_read(dmix->timer, &rbuf, sizeof(rbuf)) > 0)
- ;
+ changed++;
}
}
+ return changed;
}
int snd_pcm_direct_timer_stop(snd_pcm_direct_t *dmix)
@@ -693,6 +697,8 @@ int snd_pcm_direct_poll_revents(snd_pcm_
int empty = 0;
assert(pfds && nfds == 1 && revents);
+
+timer_changed:
events = pfds[0].revents;
if (events & POLLIN) {
snd_pcm_uframes_t avail;
@@ -720,7 +726,16 @@ int snd_pcm_direct_poll_revents(snd_pcm_
break;
default:
if (empty) {
- snd_pcm_direct_clear_timer_queue(dmix);
+ /* here we have a race condition:
+ * if period event arrived after the avail_update call
+ * above we might clear this event with the following
+ * clear_timer_queue.
+ * There is no way to do this in atomic manner, so we
+ * need to recheck avail_update if we successfully
+ * cleared a poll event.
+ */
+ if (snd_pcm_direct_clear_timer_queue(dmix))
+ goto timer_changed;
events &= ~(POLLOUT|POLLIN);
/* additional check */
switch (__snd_pcm_state(pcm)) {
--- a/src/pcm/pcm_direct.h
+++ b/src/pcm/pcm_direct.h
@@ -322,7 +322,7 @@ int snd_pcm_direct_munmap(snd_pcm_t *pcm
int snd_pcm_direct_prepare(snd_pcm_t *pcm);
int snd_pcm_direct_resume(snd_pcm_t *pcm);
int snd_pcm_direct_timer_stop(snd_pcm_direct_t *dmix);
-void snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix);
+int snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix);
int snd_pcm_direct_set_timer_params(snd_pcm_direct_t *dmix);
int snd_pcm_direct_open_secondary_client(snd_pcm_t **spcmp, snd_pcm_direct_t *dmix, const char *client_name);

View File

@ -0,0 +1,77 @@
From fe65b00f337dd08f8c14d54b0ce6b516424d78e8 Mon Sep 17 00:00:00 2001
From: Timo Wischer <twischer@de.adit-jv.com>
Date: Fri, 17 Feb 2017 12:47:17 +0530
Subject: [PATCH 28/43] pcm: file: Enable file writing for capture path
This commit reverts parts of commit 4081be0b87ab9fa53a8906e66bc240f18a7a9a54,
because it is realy useful to use the file plugin in a capture path for
debugging. Also it fixes the truncate issue mentioned in above commit.
Additionally following MMAP access issue is considered:
$ arecord -D teeraw -M -d5 arecord.wav
Recording WAVE 'arecord.wav' : Unsigned 8 bit, Rate 8000 Hz, Mono
ALSA lib pcm/pcm_file.c:358:(snd_pcm_file_write_bytes)
write failed: Bad file descriptor
ALSA lib pcm/pcm_file.c:358:(snd_pcm_file_write_bytes)
write failed: Bad file descriptor
arecord: pcm/pcm_file.c:397: snd_pcm_file_add_frames:
Assertion `file->wbuf_used_bytes < file->wbuf_size_bytes' failed.
Aborted by signal Aborted...
Signed-off-by: Timo Wischer <twischer@de.adit-jv.com>
Signed-off-by: Mounesh Sutar <sutar.mounesh@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_file.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
--- a/src/pcm/pcm_file.c
+++ b/src/pcm/pcm_file.c
@@ -544,6 +544,7 @@ static snd_pcm_sframes_t snd_pcm_file_wr
static snd_pcm_sframes_t snd_pcm_file_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size)
{
snd_pcm_file_t *file = pcm->private_data;
+ snd_pcm_channel_area_t areas[pcm->channels];
snd_pcm_sframes_t n;
n = _snd_pcm_readi(file->gen.slave, buffer, size);
@@ -555,8 +556,10 @@ static snd_pcm_sframes_t snd_pcm_file_re
__snd_pcm_unlock(pcm);
if (n < 0)
return n;
- return n * 8 / pcm->frame_bits;
+ n = n * 8 / pcm->frame_bits;
}
+ snd_pcm_areas_from_buf(pcm, areas, buffer);
+ snd_pcm_file_add_frames(pcm, areas, 0, n);
return n;
}
@@ -564,6 +567,7 @@ static snd_pcm_sframes_t snd_pcm_file_re
static snd_pcm_sframes_t snd_pcm_file_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
{
snd_pcm_file_t *file = pcm->private_data;
+ snd_pcm_channel_area_t areas[pcm->channels];
snd_pcm_sframes_t n;
if (file->ifd >= 0) {
@@ -572,6 +576,10 @@ static snd_pcm_sframes_t snd_pcm_file_re
}
n = _snd_pcm_readn(file->gen.slave, bufs, size);
+ if (n > 0) {
+ snd_pcm_areas_from_bufs(pcm, areas, bufs);
+ snd_pcm_file_add_frames(pcm, areas, 0, n);
+ }
return n;
}
@@ -635,7 +643,7 @@ static int snd_pcm_file_hw_params(snd_pc
a->first = slave->sample_bits * channel;
a->step = slave->frame_bits;
}
- if ((file->fd < 0) && (pcm->stream == SND_PCM_STREAM_PLAYBACK)) {
+ if (file->fd < 0) {
err = snd_pcm_file_open_output_file(file);
if (err < 0) {
SYSERR("failed opening output file %s", file->fname);

View File

@ -0,0 +1,42 @@
From a50496346f39e91ecd42cb09bc5c95321131be55 Mon Sep 17 00:00:00 2001
From: Andreas Pape <apape@de.adit-jv.com>
Date: Fri, 17 Feb 2017 12:47:36 +0530
Subject: [PATCH 29/43] pcm: status dump fix timestamp formatting
nanosecond part formatted with %06 will give incorrect/confusing results:
trigger_time: 154.9748287
trigger_time: 154.60109090
trigger_time: 154.110425257
time seems to run backwards...
This patch converts to us before printing
which gives the correct/expected result:
trigger_time: 154.009748
trigger_time: 154.060109
trigger_time: 154.110425
Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
Signed-off-by: Mounesh Sutar <sutar.mounesh@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -2194,9 +2194,10 @@ int snd_pcm_status_dump(snd_pcm_status_t
assert(status);
snd_output_printf(out, " state : %s\n", snd_pcm_state_name((snd_pcm_state_t) status->state));
snd_output_printf(out, " trigger_time: %ld.%06ld\n",
- status->trigger_tstamp.tv_sec, status->trigger_tstamp.tv_nsec);
+ status->trigger_tstamp.tv_sec,
+ status->trigger_tstamp.tv_nsec / 1000);
snd_output_printf(out, " tstamp : %ld.%06ld\n",
- status->tstamp.tv_sec, status->tstamp.tv_nsec);
+ status->tstamp.tv_sec, status->tstamp.tv_nsec / 1000);
snd_output_printf(out, " delay : %ld\n", (long)status->delay);
snd_output_printf(out, " avail : %ld\n", (long)status->avail);
snd_output_printf(out, " avail_max : %ld\n", (long)status->avail_max);

View File

@ -0,0 +1,27 @@
From fbb957138135e09ed9fd0180dcad549aad815465 Mon Sep 17 00:00:00 2001
From: Awais Belal <awais_belal@mentor.com>
Date: Fri, 17 Feb 2017 12:47:49 +0530
Subject: [PATCH 30/43] pcm: extplug: refinement of masks in extplug
It should be possible to use empty mask format with extplug.
The refinement of mask via extplug is now modified,
to accept empty masks as well to work properly.
Signed-off-by: Awais Belal <awais_belal@mentor.com>
Signed-off-by: Mounesh Sutar <sutar.mounesh@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_extplug.c | 2 ++
1 file changed, 2 insertions(+)
--- a/src/pcm/pcm_extplug.c
+++ b/src/pcm/pcm_extplug.c
@@ -172,6 +172,8 @@ int snd_ext_parm_mask_refine(snd_mask_t
unsigned int i;
parm += type;
+ if (!parm->active)
+ return 0;
memset(&bits, 0, sizeof(bits));
for (i = 0; i < parm->num_list; i++)
bits.bits[parm->list[i] / 32] |= 1U << (parm->list[i] % 32);

View File

@ -0,0 +1,185 @@
From 97be19cf6f44fc5084828114c53281dff6e365b4 Mon Sep 17 00:00:00 2001
From: Alan Young <consult.awy@gmail.com>
Date: Thu, 7 Apr 2016 09:15:04 +0100
Subject: [PATCH 31/43] pcm: rate: Add capability to pass configuration node to
plugins
If a rate plugin uses a node (compound) instead of a plain string for
its "converter", and that compound is not a simple string array, then
the compound will be passed as an additional parameter to the new plugin
open() function (SND_PCM_RATE_PLUGIN_CONF_ENTRY(XXX)). The previous
open() function (SND_PCM_RATE_PLUGIN_ENTRY(XXX)) will be called if the
CONF version is not found. It is up to the plugin to determine whether
the presence of the conf parameter is mandatory.
Signed-off-by: Alan Young <consult.awy@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/pcm_rate.h | 5 ++-
src/pcm/pcm_rate.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++------
2 files changed, 82 insertions(+), 10 deletions(-)
--- a/include/pcm_rate.h
+++ b/include/pcm_rate.h
@@ -120,11 +120,14 @@ typedef struct snd_pcm_rate_ops {
typedef int (*snd_pcm_rate_open_func_t)(unsigned int version, void **objp,
snd_pcm_rate_ops_t *opsp);
+typedef int (*snd_pcm_rate_open_conf_func_t)(unsigned int version, void **objp,
+ snd_pcm_rate_ops_t *opsp, const snd_config_t *conf);
+
/**
* Define the object entry for external PCM rate-converter plugins
*/
#define SND_PCM_RATE_PLUGIN_ENTRY(name) _snd_pcm_rate_##name##_open
-
+#define SND_PCM_RATE_PLUGIN_CONF_ENTRY(name) _snd_pcm_rate_##name##_open_conf
#ifndef DOC_HIDDEN
/* old rate_ops for protocol version 0x010001 */
--- a/src/pcm/pcm_rate.c
+++ b/src/pcm/pcm_rate.c
@@ -1258,26 +1258,48 @@ static const char *const default_rate_pl
"speexrate", "linear", NULL
};
-static int rate_open_func(snd_pcm_rate_t *rate, const char *type, int verbose)
+static int rate_open_func(snd_pcm_rate_t *rate, const char *type, const snd_config_t *converter_conf, int verbose)
{
- char open_name[64], lib_name[128], *lib = NULL;
+ char open_name[64], open_conf_name[64], lib_name[128], *lib = NULL;
snd_pcm_rate_open_func_t open_func;
+ snd_pcm_rate_open_conf_func_t open_conf_func;
int err;
snprintf(open_name, sizeof(open_name), "_snd_pcm_rate_%s_open", type);
+ snprintf(open_conf_name, sizeof(open_conf_name), "_snd_pcm_rate_%s_open_conf", type);
if (!is_builtin_plugin(type)) {
snprintf(lib_name, sizeof(lib_name),
"%s/libasound_module_rate_%s.so", ALSA_PLUGIN_DIR, type);
lib = lib_name;
}
+
+ rate->rate_min = SND_PCM_PLUGIN_RATE_MIN;
+ rate->rate_max = SND_PCM_PLUGIN_RATE_MAX;
+ rate->plugin_version = SND_PCM_RATE_PLUGIN_VERSION;
+
+ open_conf_func = snd_dlobj_cache_get(lib, open_conf_name, NULL, verbose && converter_conf != NULL);
+ if (open_conf_func) {
+ err = open_conf_func(SND_PCM_RATE_PLUGIN_VERSION,
+ &rate->obj, &rate->ops, converter_conf);
+ if (!err) {
+ rate->plugin_version = rate->ops.version;
+ if (rate->ops.get_supported_rates)
+ rate->ops.get_supported_rates(rate->obj,
+ &rate->rate_min,
+ &rate->rate_max);
+ rate->open_func = open_conf_func;
+ return 0;
+ } else {
+ snd_dlobj_cache_put(open_conf_func);
+ return err;
+ }
+ }
+
open_func = snd_dlobj_cache_get(lib, open_name, NULL, verbose);
if (!open_func)
return -ENOENT;
rate->open_func = open_func;
- rate->rate_min = SND_PCM_PLUGIN_RATE_MIN;
- rate->rate_max = SND_PCM_PLUGIN_RATE_MAX;
- rate->plugin_version = SND_PCM_RATE_PLUGIN_VERSION;
err = open_func(SND_PCM_RATE_PLUGIN_VERSION, &rate->obj, &rate->ops);
if (!err) {
@@ -1301,6 +1323,30 @@ static int rate_open_func(snd_pcm_rate_t
}
#endif
+/*
+ * If the conf is an array of alternatives then the id of
+ * the first element will be "0" (or maybe NULL). Otherwise assume it is
+ * a structure.
+ */
+static int is_string_array(const snd_config_t *conf)
+{
+ snd_config_iterator_t i;
+
+ if (snd_config_get_type(conf) != SND_CONFIG_TYPE_COMPOUND)
+ return 0;
+
+ i = snd_config_iterator_first(conf);
+ if (i && i != snd_config_iterator_end(conf)) {
+ snd_config_t *n = snd_config_iterator_entry(i);
+ const char *id;
+ snd_config_get_id(n, &id);
+ if (id && strcmp(id, "0") != 0)
+ return 0;
+ }
+
+ return 1;
+}
+
/**
* \brief Creates a new rate PCM
* \param pcmp Returns created PCM handle
@@ -1353,24 +1399,42 @@ int snd_pcm_rate_open(snd_pcm_t **pcmp,
if (!converter) {
const char *const *types;
for (types = default_rate_plugins; *types; types++) {
- err = rate_open_func(rate, *types, 0);
+ err = rate_open_func(rate, *types, NULL, 0);
if (!err) {
type = *types;
break;
}
}
} else if (!snd_config_get_string(converter, &type))
- err = rate_open_func(rate, type, 1);
- else if (snd_config_get_type(converter) == SND_CONFIG_TYPE_COMPOUND) {
+ err = rate_open_func(rate, type, NULL, 1);
+ else if (is_string_array(converter)) {
snd_config_iterator_t i, next;
snd_config_for_each(i, next, converter) {
snd_config_t *n = snd_config_iterator_entry(i);
if (snd_config_get_string(n, &type) < 0)
break;
- err = rate_open_func(rate, type, 0);
+ err = rate_open_func(rate, type, NULL, 0);
if (!err)
break;
}
+ } else if (snd_config_get_type(converter) == SND_CONFIG_TYPE_COMPOUND) {
+ snd_config_iterator_t i, next;
+ snd_config_for_each(i, next, converter) {
+ snd_config_t *n = snd_config_iterator_entry(i);
+ const char *id;
+ snd_config_get_id(n, &id);
+ if (strcmp(id, "name") != 0)
+ continue;
+ snd_config_get_string(n, &type);
+ break;
+ }
+ if (!type) {
+ SNDERR("No name given for rate converter");
+ snd_pcm_free(pcm);
+ free(rate);
+ return -EINVAL;
+ }
+ err = rate_open_func(rate, type, converter, 1);
} else {
SNDERR("Invalid type for rate converter");
snd_pcm_free(pcm);
@@ -1439,6 +1503,11 @@ pcm.name {
converter [ STR1 STR2 ... ] # optional
# Converter type, default is taken from
# defaults.pcm.rate_converter
+ # or
+ converter { # optional
+ name STR # Convertor type
+ xxx yyy # optional convertor-specific configuration
+ }
}
\endcode

View File

@ -0,0 +1,60 @@
From 3bad0a21b4d13d8d10691f382c836897fa7a7cb9 Mon Sep 17 00:00:00 2001
From: Breno Leitao <leitao@debian.org>
Date: Wed, 22 Feb 2017 16:45:00 -0300
Subject: [PATCH 32/43] Drop ppc64-specific workaround for versioned symbols
Currently aserver fails to build when using parameter
--without-versioned, due to an workaround for ppc64
(06221f86d207cb33ddd4867ca5301eeb247c4400). This workaround is
not required anymore on the ppc64 ABI v2, and, in fact is breaking the
compilation. Reverting this commit
Signed-off-by: Breno Leitao <leitao@debian.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/alsa-symbols.h | 17 -----------------
1 file changed, 17 deletions(-)
--- a/include/alsa-symbols.h
+++ b/include/alsa-symbols.h
@@ -29,19 +29,10 @@
#define INTERNAL_CONCAT2_2(Pre, Post) Pre##Post
#define INTERNAL(Name) INTERNAL_CONCAT2_2(__, Name)
-#ifdef __powerpc64__
-# define symbol_version(real, name, version) \
- __asm__ (".symver " ASM_NAME(#real) "," ASM_NAME(#name) "@" #version); \
- __asm__ (".symver ." ASM_NAME(#real) ",." ASM_NAME(#name) "@" #version)
-# define default_symbol_version(real, name, version) \
- __asm__ (".symver " ASM_NAME(#real) "," ASM_NAME(#name) "@@" #version); \
- __asm__ (".symver ." ASM_NAME(#real) ",." ASM_NAME(#name) "@@" #version)
-#else
# define symbol_version(real, name, version) \
__asm__ (".symver " ASM_NAME(#real) "," ASM_NAME(#name) "@" #version)
# define default_symbol_version(real, name, version) \
__asm__ (".symver " ASM_NAME(#real) "," ASM_NAME(#name) "@@" #version)
-#endif
#ifdef USE_VERSIONED_SYMBOLS
#define use_symbol_version(real, name, version) \
@@ -50,13 +41,6 @@
default_symbol_version(real, name, version)
#else
#define use_symbol_version(real, name, version) /* nothing */
-#ifdef __powerpc64__
-#define use_default_symbol_version(real, name, version) \
- __asm__ (".weak " ASM_NAME(#name)); \
- __asm__ (".weak ." ASM_NAME(#name)); \
- __asm__ (".set " ASM_NAME(#name) "," ASM_NAME(#real)); \
- __asm__ (".set ." ASM_NAME(#name) ",." ASM_NAME(#real))
-#else
#if defined(__alpha__) || defined(__mips__)
#define use_default_symbol_version(real, name, version) \
__asm__ (".weak " ASM_NAME(#name)); \
@@ -67,6 +51,5 @@
__asm__ (".set " ASM_NAME(#name) "," ASM_NAME(#real))
#endif
#endif
-#endif
#endif /* __ALSA_SYMBOLS_H */

View File

@ -0,0 +1,68 @@
From b0e4652881f883023d2b190cf3897b7494d8d0ed Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Mon, 27 Feb 2017 09:25:24 +0100
Subject: [PATCH 33/43] pcm_plugin: unify the snd_pcm_mmap_begin result value
checking
---
src/pcm/pcm_plugin.c | 26 +++++++++++++++++++-------
1 file changed, 19 insertions(+), 7 deletions(-)
--- a/src/pcm/pcm_plugin.c
+++ b/src/pcm/pcm_plugin.c
@@ -251,8 +251,12 @@ static snd_pcm_sframes_t snd_pcm_plugin_
snd_pcm_uframes_t slave_offset;
snd_pcm_uframes_t slave_frames = ULONG_MAX;
- err = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
- if (err < 0 || slave_frames == 0)
+ result = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
+ if (result < 0) {
+ err = result;
+ goto error;
+ }
+ if (slave_frames == 0)
break;
frames = plugin->write(pcm, areas, offset, frames,
slave_areas, slave_offset, &slave_frames);
@@ -304,7 +308,11 @@ static snd_pcm_sframes_t snd_pcm_plugin_
snd_pcm_uframes_t slave_offset;
snd_pcm_uframes_t slave_frames = ULONG_MAX;
- snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
+ result = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
+ if (result < 0) {
+ err = result;
+ goto error;
+ }
if (slave_frames == 0)
break;
frames = (plugin->read)(pcm, areas, offset, frames,
@@ -409,9 +417,11 @@ snd_pcm_plugin_mmap_commit(snd_pcm_t *pc
snd_pcm_uframes_t slave_frames = ULONG_MAX;
snd_pcm_sframes_t result;
- err = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
- if (err < 0)
+ result = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
+ if (result < 0) {
+ err = result;
goto error;
+ }
if (frames > cont)
frames = cont;
frames = plugin->write(pcm, areas, appl_offset, frames,
@@ -481,9 +491,11 @@ static snd_pcm_sframes_t snd_pcm_plugin_
snd_pcm_uframes_t slave_frames = ULONG_MAX;
snd_pcm_sframes_t result;
- err = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
- if (err < 0)
+ result = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
+ if (result < 0) {
+ err = result;
goto error;
+ }
if (frames > cont)
frames = cont;
frames = (plugin->read)(pcm, areas, hw_offset, frames,

View File

@ -0,0 +1,46 @@
From 8a38461fac67f6542308063ba8e9887a1a2fa84e Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Mon, 27 Feb 2017 09:26:33 +0100
Subject: [PATCH 34/43] always handle return value from snd_config_get_id()
(coverity)
---
src/pcm/pcm_rate.c | 6 ++++--
src/topology/data.c | 4 ++--
2 files changed, 6 insertions(+), 4 deletions(-)
--- a/src/pcm/pcm_rate.c
+++ b/src/pcm/pcm_rate.c
@@ -1339,7 +1339,8 @@ static int is_string_array(const snd_con
if (i && i != snd_config_iterator_end(conf)) {
snd_config_t *n = snd_config_iterator_entry(i);
const char *id;
- snd_config_get_id(n, &id);
+ if (snd_config_get_id(n, &id) < 0)
+ return 0;
if (id && strcmp(id, "0") != 0)
return 0;
}
@@ -1422,7 +1423,8 @@ int snd_pcm_rate_open(snd_pcm_t **pcmp,
snd_config_for_each(i, next, converter) {
snd_config_t *n = snd_config_iterator_entry(i);
const char *id;
- snd_config_get_id(n, &id);
+ if (snd_config_get_id(n, &id) < 0)
+ continue;
if (strcmp(id, "name") != 0)
continue;
snd_config_get_string(n, &type);
--- a/src/topology/data.c
+++ b/src/topology/data.c
@@ -653,8 +653,8 @@ static int parse_tuple_sets(snd_config_t
int err;
if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
- snd_config_get_id(cfg, &id);
- SNDERR("error: compound type expected for %s", id);
+ if (snd_config_get_id(cfg, &id) >= 0)
+ SNDERR("error: compound type expected for %s", id);
return -EINVAL;
}

View File

@ -0,0 +1,31 @@
From b96f6f47852aa145645fb8626d009ec532246e55 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Mon, 27 Feb 2017 09:29:18 +0100
Subject: [PATCH 35/43] pcm file plugin: handle snd_pcm_mmap_begin() error path
in snd_pcm_file_mmap_commit()
---
src/pcm/pcm_file.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
--- a/src/pcm/pcm_file.c
+++ b/src/pcm/pcm_file.c
@@ -593,11 +593,13 @@ static snd_pcm_sframes_t snd_pcm_file_mm
const snd_pcm_channel_area_t *areas;
snd_pcm_sframes_t result;
- snd_pcm_mmap_begin(file->gen.slave, &areas, &ofs, &siz);
- assert(ofs == offset && siz == size);
- result = snd_pcm_mmap_commit(file->gen.slave, ofs, siz);
- if (result > 0)
- snd_pcm_file_add_frames(pcm, areas, ofs, result);
+ result = snd_pcm_mmap_begin(file->gen.slave, &areas, &ofs, &siz);
+ if (result >= 0) {
+ assert(ofs == offset && siz == size);
+ result = snd_pcm_mmap_commit(file->gen.slave, ofs, siz);
+ if (result > 0)
+ snd_pcm_file_add_frames(pcm, areas, ofs, result);
+ }
return result;
}

View File

@ -0,0 +1,83 @@
From db0e1dcfc22fb2e408a12993cda2d604e0fb10f8 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Mon, 27 Feb 2017 09:46:18 +0100
Subject: [PATCH 36/43] topology: coverity - remove dead code
---
src/topology/ctl.c | 5 ++---
src/topology/data.c | 2 +-
src/topology/pcm.c | 17 +++++++----------
3 files changed, 10 insertions(+), 14 deletions(-)
--- a/src/topology/ctl.c
+++ b/src/topology/ctl.c
@@ -173,7 +173,7 @@ static int tplg_build_enum_control(snd_t
{
struct tplg_ref *ref;
struct list_head *base, *pos;
- int err = 0;
+ int err;
base = &elem->ref_list;
@@ -198,8 +198,7 @@ static int tplg_build_enum_control(snd_t
SNDERR("error: cannot find '%s' referenced by"
" control '%s'\n", ref->id, elem->id);
return -EINVAL;
- } else if (err < 0)
- return err;
+ }
}
return 0;
--- a/src/topology/data.c
+++ b/src/topology/data.c
@@ -917,7 +917,7 @@ int tplg_build_manifest_data(snd_tplg_t
list_for_each(pos, base) {
ref = list_entry(pos, struct tplg_ref, list);
- if (ref->id == NULL || ref->elem)
+ if (ref->elem)
continue;
if (ref->type == SND_TPLG_TYPE_DATA) {
--- a/src/topology/pcm.c
+++ b/src/topology/pcm.c
@@ -79,8 +79,8 @@ static int build_pcm(snd_tplg_t *tplg, s
int err;
err = tplg_build_stream_caps(tplg, elem->id, elem->pcm->caps);
- if (err < 0)
- return err;
+ if (err < 0)
+ return err;
/* merge private data from the referenced data elements */
base = &elem->ref_list;
@@ -96,8 +96,7 @@ static int build_pcm(snd_tplg_t *tplg, s
SNDERR("error: cannot find '%s' referenced by"
" PCM '%s'\n", ref->id, elem->id);
return -EINVAL;
- } else if (err < 0)
- return err;
+ }
}
return 0;
@@ -1208,12 +1207,10 @@ int tplg_add_link_object(snd_tplg_t *tpl
/* ID and names */
link->id = link_tpl->id;
- if (link->name)
- elem_copy_text(link->name, link_tpl->name,
- SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
- if (link->stream_name)
- elem_copy_text(link->stream_name, link_tpl->stream_name,
- SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
+ elem_copy_text(link->name, link_tpl->name,
+ SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
+ elem_copy_text(link->stream_name, link_tpl->stream_name,
+ SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
/* stream configs */
if (link_tpl->num_streams > SND_SOC_TPLG_STREAM_CONFIG_MAX)

View File

@ -0,0 +1,22 @@
From ad188bbf7813eab6f42dcdf617aa947107118857 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Mon, 27 Feb 2017 09:53:26 +0100
Subject: [PATCH 37/43] ucm parser: fix possible string overflow in
uc_mgr_import_master_config()
---
src/ucm/parser.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/src/ucm/parser.c
+++ b/src/ucm/parser.c
@@ -1453,7 +1453,8 @@ int uc_mgr_import_master_config(snd_use_
err = load_master_config(uc_mgr->card_name, &cfg);
if (err < 0)
return err;
- strcpy(uc_mgr->conf_file_name, uc_mgr->card_name);
+ strncpy(uc_mgr->conf_file_name, uc_mgr->card_name, MAX_CARD_LONG_NAME);
+ uc_mgr->conf_file_name[MAX_CARD_LONG_NAME-1] = '\0';
}
err = parse_master_file(uc_mgr, cfg);

View File

@ -0,0 +1,68 @@
From fdc898d41135b26772d0fffe07e9eb0de6597125 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Mon, 20 Mar 2017 08:34:33 +0100
Subject: [PATCH 38/43] dmix plugin: fix drain for nonblock mode
---
src/pcm/pcm_dmix.c | 24 ++++++++++++++++--------
1 file changed, 16 insertions(+), 8 deletions(-)
--- a/src/pcm/pcm_dmix.c
+++ b/src/pcm/pcm_dmix.c
@@ -628,7 +628,7 @@ static int __snd_pcm_dmix_drain(snd_pcm_
{
snd_pcm_direct_t *dmix = pcm->private_data;
snd_pcm_uframes_t stop_threshold;
- int err;
+ int err = 0;
switch (snd_pcm_state(dmix->spcm)) {
case SND_PCM_STATE_SUSPENDED:
@@ -639,8 +639,6 @@ static int __snd_pcm_dmix_drain(snd_pcm_
if (dmix->state == SND_PCM_STATE_OPEN)
return -EBADFD;
- if (pcm->mode & SND_PCM_NONBLOCK)
- return -EAGAIN;
if (dmix->state == SND_PCM_STATE_PREPARED) {
if (snd_pcm_mmap_playback_hw_avail(pcm) > 0)
snd_pcm_dmix_start(pcm);
@@ -663,23 +661,33 @@ static int __snd_pcm_dmix_drain(snd_pcm_
err = snd_pcm_dmix_sync_ptr(pcm);
if (err < 0) {
snd_pcm_dmix_drop(pcm);
- return err;
+ goto done;
}
if (dmix->state == SND_PCM_STATE_DRAINING) {
snd_pcm_dmix_sync_area(pcm);
- snd_pcm_wait_nocheck(pcm, -1);
- snd_pcm_direct_clear_timer_queue(dmix); /* force poll to wait */
+ if ((pcm->mode & SND_PCM_NONBLOCK) == 0) {
+ snd_pcm_wait_nocheck(pcm, -1);
+ snd_pcm_direct_clear_timer_queue(dmix); /* force poll to wait */
+ }
switch (snd_pcm_state(dmix->spcm)) {
case SND_PCM_STATE_SUSPENDED:
- return -ESTRPIPE;
+ err = -ESTRPIPE;
+ goto done;
+ case SND_PCM_STATE_DRAINING:
+ if (pcm->mode & SND_PCM_NONBLOCK) {
+ err = -EAGAIN;
+ goto done;
+ }
+ break;
default:
break;
}
}
} while (dmix->state == SND_PCM_STATE_DRAINING);
+done:
pcm->stop_threshold = stop_threshold;
- return 0;
+ return err;
}
static int snd_pcm_dmix_drain(snd_pcm_t *pcm)

View File

@ -0,0 +1,34 @@
From e4377b16454f3b7b222613a571bf4244ebd28e56 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Mon, 20 Mar 2017 08:41:53 +0100
Subject: [PATCH 39/43] dmix plugin: drain - quickfix for the previous patch
---
src/pcm/pcm_dmix.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
--- a/src/pcm/pcm_dmix.c
+++ b/src/pcm/pcm_dmix.c
@@ -674,16 +674,16 @@ static int __snd_pcm_dmix_drain(snd_pcm_
case SND_PCM_STATE_SUSPENDED:
err = -ESTRPIPE;
goto done;
- case SND_PCM_STATE_DRAINING:
- if (pcm->mode & SND_PCM_NONBLOCK) {
- err = -EAGAIN;
- goto done;
- }
- break;
default:
break;
}
}
+ if (pcm->mode & SND_PCM_NONBLOCK) {
+ if (dmix->state == SND_PCM_STATE_DRAINING) {
+ err = -EAGAIN;
+ goto done;
+ }
+ }
} while (dmix->state == SND_PCM_STATE_DRAINING);
done:
pcm->stop_threshold = stop_threshold;

View File

@ -0,0 +1,28 @@
From d71f294566e53c967a6a1e2d5c684499ec390d69 Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Sat, 18 Mar 2017 23:10:33 +0100
Subject: [PATCH 40/43] rawmidi: virtual: fix reading into a small buffer
In the special case for handling partial messages, the pointer
calculations were wrong, which would result in data corruption.
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Reviewd-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/rawmidi/rawmidi_virt.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/src/rawmidi/rawmidi_virt.c
+++ b/src/rawmidi/rawmidi_virt.c
@@ -263,8 +263,8 @@ static ssize_t snd_rawmidi_virtual_read(
}
size1 = virt->in_buf_size - virt->in_buf_ofs;
if ((size_t)size1 > size) {
- virt->in_buf_ofs += size1 - size;
- memcpy(buffer, virt->in_buf_ptr, size);
+ memcpy(buffer, virt->in_buf_ptr + virt->in_buf_ofs, size);
+ virt->in_buf_ofs += size;
result += size;
break;
}

View File

@ -0,0 +1,104 @@
From 7c2093b1c136e0766116a0b88b565b99176aed19 Mon Sep 17 00:00:00 2001
From: Boris Brezillon <boris.brezillon@free-electrons.com>
Date: Thu, 2 Mar 2017 11:49:33 +0100
Subject: [PATCH 41/43] conf/cards: add VC4-HDMI card
Add a conf file for the VC4-HDMI sound card.
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Tested-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/conf/cards/Makefile.am | 1
src/conf/cards/aliases.conf | 1
src/conf/cards/vc4-hdmi.conf | 64 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 66 insertions(+)
create mode 100644 src/conf/cards/vc4-hdmi.conf
--- a/src/conf/cards/Makefile.am
+++ b/src/conf/cards/Makefile.am
@@ -51,6 +51,7 @@ cfg_files = aliases.conf \
TRID4DWAVENX.conf \
USB-Audio.conf \
YMF744.conf \
+ vc4-hdmi.conf \
VIA686A.conf \
VIA8233.conf \
VIA8233A.conf \
--- a/src/conf/cards/aliases.conf
+++ b/src/conf/cards/aliases.conf
@@ -56,6 +56,7 @@ AV200 cards.CMI8788
CMI8786 cards.CMI8788
CMI8787 cards.CMI8788
pistachio cards.pistachio-card
+VC4-HDMI cards.vc4-hdmi
<confdir:pcm/default.conf>
<confdir:pcm/dmix.conf>
--- /dev/null
+++ b/src/conf/cards/vc4-hdmi.conf
@@ -0,0 +1,64 @@
+#
+# Configuration for the VC4-HDMI sound card using software IEC958
+# subframe conversion
+#
+
+<confdir:pcm/front.conf>
+
+vc4-hdmi.pcm.front.0 {
+ @args [ CARD ]
+ @args.CARD {
+ type string
+ }
+ type hw
+ card $CARD
+}
+
+# default with dmix
+vc4-hdmi.pcm.default {
+ @args [ CARD ]
+ @args.CARD {
+ type string
+ }
+ type asym
+ playback.pcm {
+ type plug
+ slave.pcm {
+ @func concat
+ strings [ "dmix:" $CARD ]
+ }
+ }
+}
+
+<confdir:pcm/iec958.conf>
+
+vc4-hdmi.pcm.iec958.0 {
+ @args [ CARD AES0 AES1 AES2 AES3 ]
+ @args.CARD {
+ type string
+ }
+ @args.AES0 {
+ type integer
+ }
+ @args.AES1 {
+ type integer
+ }
+ @args.AES2 {
+ type integer
+ }
+ @args.AES3 {
+ type integer
+ }
+ type iec958
+ slave {
+ format IEC958_SUBFRAME_LE
+ pcm {
+ type plug
+ slave.pcm {
+ type hw
+ card $CARD
+ }
+ }
+ }
+ status [ $AES0 $AES1 $AES2 $AES3 ]
+}

View File

@ -0,0 +1,63 @@
From 653faa8991aa3460c42d9688ff83846807f3ad51 Mon Sep 17 00:00:00 2001
From: Andreas Pape <apape@de.adit-jv.com>
Date: Tue, 21 Mar 2017 18:28:18 +0530
Subject: [PATCH 42/43] pcm:plug: save converter config
Passed config is freed after call to open, thus it is invalid when
trying to extract the converter name. So config entry is saved
for later usage.
Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
Signed-off-by: Mounesh Sutar <sutar.mounesh@gmail.com>
Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_plug.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
--- a/src/pcm/pcm_plug.c
+++ b/src/pcm/pcm_plug.c
@@ -50,7 +50,7 @@ typedef struct {
snd_pcm_format_t sformat;
int schannels;
int srate;
- const snd_config_t *rate_converter;
+ snd_config_t *rate_converter;
enum snd_pcm_plug_route_policy route_policy;
snd_pcm_route_ttable_entry_t *ttable;
int ttable_ok;
@@ -64,6 +64,10 @@ static int snd_pcm_plug_close(snd_pcm_t
snd_pcm_plug_t *plug = pcm->private_data;
int err, result = 0;
free(plug->ttable);
+ if (plug->rate_converter) {
+ snd_config_delete(plug->rate_converter);
+ plug->rate_converter = NULL;
+ }
assert(plug->gen.slave == plug->req_slave);
if (plug->gen.close_slave) {
snd_pcm_unlink_hw_ptr(pcm, plug->req_slave);
@@ -1108,7 +1112,6 @@ int snd_pcm_plug_open(snd_pcm_t **pcmp,
plug->sformat = sformat;
plug->schannels = schannels;
plug->srate = srate;
- plug->rate_converter = rate_converter;
plug->gen.slave = plug->req_slave = slave;
plug->gen.close_slave = close_slave;
plug->route_policy = route_policy;
@@ -1125,6 +1128,15 @@ int snd_pcm_plug_open(snd_pcm_t **pcmp,
pcm->ops = &snd_pcm_plug_ops;
pcm->fast_ops = slave->fast_ops;
pcm->fast_op_arg = slave->fast_op_arg;
+ if (rate_converter) {
+ err = snd_config_copy(&plug->rate_converter,
+ (snd_config_t *)rate_converter);
+ if (err < 0) {
+ snd_pcm_free(pcm);
+ free(plug);
+ return err;
+ }
+ }
pcm->private_data = plug;
pcm->poll_fd = slave->poll_fd;
pcm->poll_events = slave->poll_events;

View File

@ -0,0 +1,108 @@
From 01bc7475c3ee4dc0c1c321c781cfb26e6e5fcb34 Mon Sep 17 00:00:00 2001
From: Andreas Pape <apape@de.adit-jv.com>
Date: Thu, 23 Mar 2017 17:10:45 +0530
Subject: [PATCH 43/43] pcm:file: delegate htimestamping to slave instead of
always getting real_htimestamp
purpose of this fix, is to read most accurate timestamps.
From documentation of /src/pcm/pcm.c, we can see:
"""" \par Timestamp mode
The timestamp mode specifies, if timestamps are activated. Currently, only #SND_PCM_TSTAMP_NONE and #SND_PCM_TSTAMP_MMAP modes are known.
The mmap mode means that timestamp is taken on every period time boundary. Corresponding position in the ring buffer assigned to timestamp can be obtained using #snd_pcm_htimestamp() function. """"
As snd_pcm_generic_htimestamp() internally calls snd_pcm_htimestamp() to read time, so accurate timestamp can be read from snd_pcm_generic_htimestamp().
Also, in case of pcm_file, if the underlying slave is hardware, then we would wish to read elapsed hardware time, as it will be the most accurate, as opposed to the elapsed wall time.
This will provide pcm_file with the most accurate timestamps.
Following are the timesamps read with timestamp enabled, for with fix and without fix scenarios:
1> With fix:
:~#time aplay --enable-tstamp -Dhtstamp_test --period-time=5000 -v -fdat /dev/urandom
Playing raw data '/dev/urandom' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
File PCM (file=/tmp/swarate_out.wav)
Final file PCM (file=/tmp/swarate_out.wav)
..
Slave: Hardware PCM card 0 'imx6q-sabresd-wm8962' device 0 subdevice 0
Its setup is:
stream : PLAYBACK
access : RW_INTERLEAVED
format : S16_LE
subformat : STD
channels : 2
rate : 48000
exact rate : 48000 (48000/1)
msbits : 16
buffer_size : 24000
period_size : 240
period_time : 5000
tstamp_mode : ENABLE
.
.
Before sleep = 142:409.807623
After sleep = 142:409.807623
Before sleep = 142:414.806016 (calling snd_pcm_htimestamp(handle, &avail, &tstamp_before))
sleep of 2 milisec
After sleep = 142:414.806016 (calling snd_pcm_htimestamp(handle, &avail, &tstamp_after)
From the above timestamps, we can see that slave has returned the same timestamps, as --period-time choosen is 5msec.
2> Without this fix:
The timestamps are returned with realtime value.
:~# time aplay --enable-tstamp -Dhtstamp_test --period-time=5000 -v -fdat /dev/urandom
Playing raw data '/dev/urandom' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
File PCM (file=/tmp/swarate_out.wav)
Final file PCM (file=/tmp/swarate_out.wav)
.
.
Slave: Hardware PCM card 0 'imx6q-sabresd-wm8962' device 0 subdevice 0
Its setup is:
stream : PLAYBACK
access : RW_INTERLEAVED
format : S16_LE
subformat : STD
channels : 2
rate : 48000
exact rate : 48000 (48000/1)
msbits : 16
buffer_size : 24000
period_size : 240
period_time : 5000
tstamp_mode : ENABLE
.
.
Before sleep = 241:136.875845 (calling snd_pcm_htimestamp(handle, &avail, &tstamp_before))
sleep of 2 milisec
After sleep = 241:139.076376 (calling snd_pcm_htimestamp(handle, &avail, &tstamp_after)
We can observe here, the timestamps shows time diff of ~2ms, which is the time gap of sleep duration.
Before sleep = 241:139.617588
After sleep = 241:141.746845
Before sleep = 241:142.291618
After sleep = 241:144.406406
Before sleep = 241:144.951421
After sleep = 241:147.066118
Before sleep = 241:147.623421
After sleep = 241:149.740573
Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
Signed-off-by: Mounesh Sutar <sutar.mounesh@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_file.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/src/pcm/pcm_file.c
+++ b/src/pcm/pcm_file.c
@@ -728,7 +728,7 @@ static const snd_pcm_fast_ops_t snd_pcm_
.poll_descriptors_count = snd_pcm_generic_poll_descriptors_count,
.poll_descriptors = snd_pcm_generic_poll_descriptors,
.poll_revents = snd_pcm_generic_poll_revents,
- .htimestamp = snd_pcm_generic_real_htimestamp,
+ .htimestamp = snd_pcm_generic_htimestamp,
};
/**

View File

@ -1,3 +1,52 @@
-------------------------------------------------------------------
Wed Mar 29 17:26:08 CEST 2017 - tiwai@suse.de
- 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
0029-pcm-status-dump-fix-timestamp-formatting.patch
0030-pcm-extplug-refinement-of-masks-in-extplug.patch
0031-pcm-rate-Add-capability-to-pass-configuration-node-t.patch
0032-Drop-ppc64-specific-workaround-for-versioned-symbols.patch
0033-pcm_plugin-unify-the-snd_pcm_mmap_begin-result-value.patch
0034-always-handle-return-value-from-snd_config_get_id-co.patch
0035-pcm-file-plugin-handle-snd_pcm_mmap_begin-error-path.patch
0036-topology-coverity-remove-dead-code.patch
0037-ucm-parser-fix-possible-string-overflow-in-uc_mgr_im.patch
0038-dmix-plugin-fix-drain-for-nonblock-mode.patch
0039-dmix-plugin-drain-quickfix-for-the-previous-patch.patch
0040-rawmidi-virtual-fix-reading-into-a-small-buffer.patch
0041-conf-cards-add-VC4-HDMI-card.patch
0042-pcm-plug-save-converter-config.patch
0043-pcm-file-delegate-htimestamping-to-slave-instead-of-.patch
-------------------------------------------------------------------
Mon Feb 13 10:28:23 UTC 2017 - tchvatal@suse.com

View File

@ -45,6 +45,49 @@ Source34: alsa-init.sh
Source40: 50-alsa.conf
Source41: install-snd-module
# upstream fixes
Patch1: 0001-ucm-Add-ATTRIBUTE_UNUSED-for-unused-parameters-of-ex.patch
Patch2: 0002-ucm-parser-needs-limits.h.patch
Patch3: 0003-pcm-direct-allow-users-to-configure-different-period.patch
Patch4: 0004-pcm-dshare-enable-silence.patch
Patch5: 0005-pcm-rate-fix-the-hw_ptr-update-until-the-boundary-av.patch
Patch6: 0006-plugin-dynamically-update-avail_min-on-slave.patch
Patch7: 0007-rate-dynamic-update-avail_min-on-slave.patch
Patch8: 0008-topology-fix-unused-const-variable-warning.patch
Patch9: 0009-seq-improve-documentation-about-new-get-pid-card-fun.patch
Patch10: 0010-pcm-direct-returning-semop-error-code-for-semaphore-.patch
Patch11: 0011-pcm-direct-Fix-for-sync-issue-on-xrun-recover.patch
Patch12: 0012-pcm-direct-check-state-before-enter-poll-on-timer.patch
Patch13: 0013-pcm-direct-don-t-return-bogus-buffer-levels-in-xrun-.patch
Patch14: 0014-conf-ucm-broxton-add-broxton-rt298-conf-files.patch
Patch15: 0015-pcm-direct-Fix-deadlock-in-poll_descriptors.patch
Patch16: 0016-ucm-Assure-the-user-input-card-name-not-to-exceed-ma.patch
Patch17: 0017-ucm-Load-device-specific-configuration-file-based-on.patch
Patch18: 0018-ucm-Add-command-get-_file-to-get-the-config-file-nam.patch
Patch19: 0019-topology-Fix-incorrect-license-in-source-comments.patch
Patch20: 0020-conf-cards-add-support-for-pistachio-card.patch
Patch21: 0021-pcm-multi-Drop-the-fixed-slave_map-in-snd_pcm_multi_.patch
Patch22: 0022-conf-Add-card-config-for-Intel-HDMI-DP-LPE-audio.patch
Patch23: 0023-pcm-Avoid-lock-for-snd_pcm_nonblock.patch
Patch24: 0024-pcm-Disable-locking-in-async-mode.patch
Patch25: 0025-pcm-dmix-Allow-disabling-x86-optimizations.patch
Patch26: 0026-pcm-dmix_rewind-corrupts-application-pointer-fix.patch
Patch27: 0027-pcm-direct-fix-race-on-clearing-timer-events.patch
Patch28: 0028-pcm-file-Enable-file-writing-for-capture-path.patch
Patch29: 0029-pcm-status-dump-fix-timestamp-formatting.patch
Patch30: 0030-pcm-extplug-refinement-of-masks-in-extplug.patch
Patch31: 0031-pcm-rate-Add-capability-to-pass-configuration-node-t.patch
Patch32: 0032-Drop-ppc64-specific-workaround-for-versioned-symbols.patch
Patch33: 0033-pcm_plugin-unify-the-snd_pcm_mmap_begin-result-value.patch
Patch34: 0034-always-handle-return-value-from-snd_config_get_id-co.patch
Patch35: 0035-pcm-file-plugin-handle-snd_pcm_mmap_begin-error-path.patch
Patch36: 0036-topology-coverity-remove-dead-code.patch
Patch37: 0037-ucm-parser-fix-possible-string-overflow-in-uc_mgr_im.patch
Patch38: 0038-dmix-plugin-fix-drain-for-nonblock-mode.patch
Patch39: 0039-dmix-plugin-drain-quickfix-for-the-previous-patch.patch
Patch40: 0040-rawmidi-virtual-fix-reading-into-a-small-buffer.patch
Patch41: 0041-conf-cards-add-VC4-HDMI-card.patch
Patch42: 0042-pcm-plug-save-converter-config.patch
Patch43: 0043-pcm-file-delegate-htimestamping-to-slave-instead-of-.patch
# rest suse patches
BuildRequires: doxygen
BuildRequires: libtool
@ -108,6 +151,49 @@ Architecture.
%prep
%setup -q -n alsa-lib-%{package_version}
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch5 -p1
%patch6 -p1
%patch7 -p1
%patch8 -p1
%patch9 -p1
%patch10 -p1
%patch11 -p1
%patch12 -p1
%patch13 -p1
%patch14 -p1
%patch15 -p1
%patch16 -p1
%patch17 -p1
%patch18 -p1
%patch19 -p1
%patch20 -p1
%patch21 -p1
%patch22 -p1
%patch23 -p1
%patch24 -p1
%patch25 -p1
%patch26 -p1
%patch27 -p1
%patch28 -p1
%patch29 -p1
%patch30 -p1
%patch31 -p1
%patch32 -p1
%patch33 -p1
%patch34 -p1
%patch35 -p1
%patch36 -p1
%patch37 -p1
%patch38 -p1
%patch39 -p1
%patch40 -p1
%patch41 -p1
%patch42 -p1
%patch43 -p1
%build
export AUTOMAKE_JOBS="%{?_smp_mflags}"