Sound-open-firmware
Threads by month
- ----- 2025 -----
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
October 2017
- 7 participants
- 26 discussions
12 Oct '17
SSP can either be in paused or prepared state during stream pause
depending on the state of the other SSP data direction. Make sure this
is taken into account.
Signed-off-by: Liam Girdwood <liam.r.girdwood(a)linux.intel.com>
---
src/drivers/ssp.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/drivers/ssp.c b/src/drivers/ssp.c
index a472974..404abd8 100644
--- a/src/drivers/ssp.c
+++ b/src/drivers/ssp.c
@@ -356,7 +356,8 @@ static int ssp_trigger(struct dai *dai, int cmd, int direction)
ssp_start(dai, direction);
break;
case COMP_CMD_RELEASE:
- if (ssp->state[direction] == COMP_STATE_PAUSED)
+ if (ssp->state[direction] == COMP_STATE_PAUSED ||
+ ssp->state[direction] == COMP_STATE_PREPARE)
ssp_start(dai, direction);
break;
case COMP_CMD_STOP:
--
2.11.0
1
10
[Sound-open-firmware] [PATCH] SRC: Support block sizes near or equal to period length
by Seppo Ingalsuo 11 Oct '17
by Seppo Ingalsuo 11 Oct '17
11 Oct '17
This patch decouples the first and second stage in two phase conversion
that is used for out/in rate fractions with high numerator or denominator
value. For e.g. 44.1 -> 48 kHz 160/147 fraction the 1st 8/7 stage and
2nd 20/21 stage are executed number of times close to period length in
time used for the scheduling rate. The number of consumed and produced
samples per copy() is no more constant. The latency of 44.1 kHz is
decreased about 2 ms and processing load is less variable.
This patch removes mute feature due to non-compatibility with variable
length data processing. It can be introduced later if needed as different
implementation.
The polyphase filter is also optimized slightly. More optimizations will
follow.
Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo(a)linux.intel.com>
---
src/audio/src.c | 354 +++++++++++++++++++++----------------------
src/audio/src_core.c | 412 ++++++++++++++++++++++++---------------------------
src/audio/src_core.h | 27 +++-
3 files changed, 395 insertions(+), 398 deletions(-)
diff --git a/src/audio/src.c b/src/audio/src.c
index de84149..993c76b 100644
--- a/src/audio/src.c
+++ b/src/audio/src.c
@@ -56,170 +56,150 @@
/* src component private data */
struct comp_data {
struct polyphase_src src[PLATFORM_MAX_CHANNELS];
+ struct src_param param;
int32_t *delay_lines;
uint32_t sink_rate;
uint32_t source_rate;
- uint32_t period_bytes; /* sink period */
- int scratch_length; /* Buffer for stage1-stage2 */
+ int32_t *sbuf_w_ptr;
+ int32_t *sbuf_r_ptr;
+ int sbuf_avail;
int sign_extend_s24; /* Set if need to copy sign bit to b24..b31 */
- void (*src_func)(struct comp_dev *dev,
+ void (* src_func)(struct comp_dev *dev,
struct comp_buffer *source,
struct comp_buffer *sink,
- int source_frames);
+ size_t *consumed,
+ size_t *produced);
};
-/* Common mute function for 2s and 1s SRC. This preserves the same
- * buffer consume and produce pattern as normal operation.
- */
-static void src_muted_s32(struct comp_buffer *source, struct comp_buffer *sink,
- int blk_in, int blk_out, int nch, int source_frames)
+/* Fallback function */
+static void fallback_s32(struct comp_dev *dev, struct comp_buffer *source,
+ struct comp_buffer *sink, size_t *bytes_read, size_t *bytes_written)
{
-
- int i;
- int32_t *dest = (int32_t *) sink->w_ptr;
- int32_t *end = (int32_t *) sink->end_addr;
- int n_read = 0;
- int n_max;
- int n;
- int n_written = 0;
-
- for (i = 0; i < source_frames - blk_in + 1; i += blk_in) {
- n_max = end - dest;
- n = nch*blk_out;
- if (n < n_max) {
- bzero(dest, n * sizeof(int32_t));
- dest += n;
- } else {
- /* Also case n_max == n is done here */
- bzero(dest, n_max * sizeof(int32_t));
- dest = (int32_t *) sink->addr;
- bzero(dest, (n - n_max) * sizeof(int32_t));
- dest += n - n_max;
- }
- n_read += nch*blk_in;
- n_written += nch*blk_out;
- }
-}
-
-/* Fallback function to just output muted samples and advance
- * pointers. Note that a buffer that is not having integer number of
- * frames in a period will drift since there is no similar blk in/out
- * check as for SRC.
- */
-static void fallback_s32(struct comp_dev *dev,
- struct comp_buffer *source,
- struct comp_buffer *sink,
- int source_frames)
-{
-
- struct comp_data *cd = comp_get_drvdata(dev);
- int nch = dev->params.channels;
- int blk_in = cd->src[0].blk_in;
- int blk_out = cd->src[0].blk_out;
-
- src_muted_s32(source, sink, blk_in, blk_out, nch, source_frames);
-
+ *bytes_read = 0;
+ *bytes_written = 0;
}
/* Normal 2 stage SRC */
static void src_2s_s32_default(struct comp_dev *dev,
struct comp_buffer *source, struct comp_buffer *sink,
- int source_frames)
+ size_t *bytes_read, size_t *bytes_written)
{
- int i;
- int j;
struct polyphase_src *s;
+ struct src_stage_prm s1;
+ struct src_stage_prm s2;
+ int j;
struct comp_data *cd = comp_get_drvdata(dev);
- int blk_in = cd->src[0].blk_in;
- int blk_out = cd->src[0].blk_out;
- int n_times1 = cd->src[0].stage1_times;
- int n_times2 = cd->src[0].stage2_times;
- int nch = dev->params.channels;
int32_t *dest = (int32_t *) sink->w_ptr;
int32_t *src = (int32_t *) source->r_ptr;
- struct src_stage_prm s1;
- struct src_stage_prm s2;
+ int32_t *sbuf_addr = cd->delay_lines;
+ int32_t *sbuf_end_addr = &cd->delay_lines[cd->param.sbuf_length];
+ int32_t sbuf_size = cd->param.sbuf_length * sizeof(int32_t);
+ const int nch = dev->params.channels;
+ const int s1_blk_in = cd->src[0].stage1->blk_in * nch;
+ const int s1_blk_out = cd->src[0].stage1->blk_out * nch;
+ const int s2_blk_in = cd->src[0].stage2->blk_in * nch;
+ const int s2_blk_out = cd->src[0].stage2->blk_out * nch;
+ int sbuf_free = cd->param.sbuf_length - cd->sbuf_avail;
+ int source_check = (source->avail >> 2) - s1_blk_in; /* for int32_t */
+ int sink_check = (sink->free >> 2) - s2_blk_out; /* For int32_t */
int n_read = 0;
int n_written = 0;
+ int n1 = 0;
+ int n2 = 0;
- if (cd->src[0].mute) {
- src_muted_s32(source, sink, blk_in, blk_out, nch, source_frames);
- return;
- }
-
- s1.times = n_times1;
+ s1.times = 1;
s1.x_end_addr = source->end_addr;
s1.x_size = source->size;
s1.x_inc = nch;
- s1.y_end_addr = &cd->delay_lines[cd->scratch_length];
- s1.y_size = cd->scratch_length * sizeof(int32_t);
- s1.y_inc = 1;
-
- s2.times = n_times2;
- s2.x_end_addr = &cd->delay_lines[cd->scratch_length];
- s2.x_size = cd->scratch_length * sizeof(int32_t);
- s2.x_inc = 1;
+ s1.y_end_addr = sbuf_end_addr;
+ s1.y_size = sbuf_size;
+ s1.y_inc = nch;
+
+ s2.times = 1;
+ s2.x_end_addr = sbuf_end_addr;
+ s2.x_size = sbuf_size;
+ s2.x_inc = nch;
s2.y_end_addr = sink->end_addr;
s2.y_size = sink->size;
s2.y_inc = nch;
- s1.x_rptr = src + nch - 1;
- s2.y_wptr = dest + nch - 1;
-
- for (j = 0; j < nch; j++) {
- s = &cd->src[j]; /* Point to src[] for this channel */
- s1.x_rptr = src++;
- s2.y_wptr = dest++;
- s1.state = &s->state1;
- s1.stage = s->stage1;
- s2.state = &s->state2;
- s2.stage = s->stage2;
-
- for (i = 0; i < source_frames - blk_in + 1; i += blk_in) {
- /* Reset output to buffer start, read interleaved */
- s1.y_wptr = cd->delay_lines;
- s2.x_rptr = cd->delay_lines;
- if (cd->sign_extend_s24) {
+ /* 1st stage runs once a long multiplied length block.
+ * The stage buffer much be large enough to fit one s1 output block
+ * plus one s2 input block plus jitter in s2 consumption.
+ */
+ while ((n1 < cd->param.stage1_times_max)
+ && (n_read <= source_check)
+ && (sbuf_free >= s1_blk_out)) {
+ for (j = 0; j < nch; j++) {
+ s = &cd->src[j]; /* Point to src[] for this channel */
+ s1.x_rptr = src++;
+ s1.y_wptr = cd->sbuf_w_ptr++;
+ src_circ_inc_wrap(&src, source->end_addr, source->size);
+ src_circ_inc_wrap(&cd->sbuf_w_ptr, sbuf_end_addr, sbuf_size);
+ s1.state = &s->state1;
+ s1.stage = s->stage1;
+ if (cd->sign_extend_s24)
src_polyphase_stage_cir_s24(&s1);
- src_polyphase_stage_cir_s24(&s2);
- } else {
+ else
src_polyphase_stage_cir(&s1);
+
+ }
+ n_read += s1_blk_in;
+ cd->sbuf_avail += s1_blk_out;
+ sbuf_free -= s1_blk_out;
+ src = s1.x_rptr - nch + 1;
+ cd->sbuf_w_ptr = s1.y_wptr - nch + 1;
+ src_circ_dec_wrap(&src, source->addr, source->size);
+ src_circ_dec_wrap(&cd->sbuf_w_ptr, sbuf_addr, sbuf_size);
+ n1++;
+ }
+
+ /* 2nd stage runs as many min size blocks as buffers allow */
+ while ((n2 < cd->param.stage2_times_max)
+ && (cd->sbuf_avail >= s2_blk_in)
+ && (n_written <= sink_check)) {
+ for (j = 0; j < nch; j++) {
+ s2.x_rptr = cd->sbuf_r_ptr++;
+ s2.y_wptr = dest++;
+ src_circ_inc_wrap(&cd->sbuf_r_ptr, sbuf_end_addr, sbuf_size);
+ src_circ_inc_wrap(&dest, sink->end_addr, sink->size);
+ s = &cd->src[j]; /* Point to src[] for this channel */
+ s2.state = &s->state2;
+ s2.stage = s->stage2;
+ if (cd->sign_extend_s24)
+ src_polyphase_stage_cir_s24(&s2);
+ else
src_polyphase_stage_cir(&s2);
- }
- n_read += blk_in;
- n_written += blk_out;
}
+ cd->sbuf_r_ptr = s2.x_rptr - nch + 1;
+ dest = s2.y_wptr - nch + 1;
+ src_circ_dec_wrap(&cd->sbuf_r_ptr, sbuf_addr, sbuf_size);
+ src_circ_dec_wrap(&dest, sink->addr, sink->size);
+ n_written += s2_blk_out;
+ cd->sbuf_avail -= s2_blk_in;
+ n2++;
}
+ *bytes_read = sizeof(int32_t) * n_read;
+ *bytes_written = sizeof(int32_t) * n_written;
}
/* 1 stage SRC for simple conversions */
static void src_1s_s32_default(struct comp_dev *dev,
struct comp_buffer *source, struct comp_buffer *sink,
- int source_frames)
+ size_t *bytes_read, size_t *bytes_written)
{
- int i;
- int j;
struct polyphase_src *s;
-
+ struct src_stage_prm s1;
+ int j;
struct comp_data *cd = comp_get_drvdata(dev);
- int blk_in = cd->src[0].blk_in;
- int blk_out = cd->src[0].blk_out;
- int n_times = cd->src[0].stage1_times;
- int nch = dev->params.channels;
int32_t *dest = (int32_t *) sink->w_ptr;
int32_t *src = (int32_t *) source->r_ptr;
+ int nch = dev->params.channels;
int n_read = 0;
int n_written = 0;
- struct src_stage_prm s1;
- if (cd->src[0].mute) {
- src_muted_s32(source, sink, blk_in, blk_out, nch,
- source_frames);
- return;
- }
-
- s1.times = n_times;
+ s1.times = cd->param.stage1_times;
s1.x_end_addr = source->end_addr;
s1.x_size = source->size;
s1.x_inc = nch;
@@ -233,20 +213,56 @@ static void src_1s_s32_default(struct comp_dev *dev,
s = &cd->src[j]; /* Point to src for this channel */
s1.x_rptr = src++;
s1.y_wptr = dest++;
+ src_circ_inc_wrap(&src, source->end_addr, source->size);
+ src_circ_inc_wrap(&dest, sink->end_addr, sink->size);
s1.state = &s->state1;
s1.stage = s->stage1;
+ if (cd->sign_extend_s24)
+ src_polyphase_stage_cir_s24(&s1);
+ else
+ src_polyphase_stage_cir(&s1);
- for (i = 0; i + blk_in - 1 < source_frames; i += blk_in) {
- if (cd->sign_extend_s24)
- src_polyphase_stage_cir_s24(&s1);
- else
- src_polyphase_stage_cir(&s1);
+ n_read += cd->param.blk_in;
+ n_written += cd->param.blk_out;
+ }
+ *bytes_read = n_read * sizeof(int32_t);
+ *bytes_written = n_written * sizeof(int32_t);
+}
- n_read += blk_in;
- n_written += blk_out;
- }
+/* A fast copy function for same in and out rate */
+static void src_copy_s32_default(struct comp_dev *dev,
+ struct comp_buffer *source, struct comp_buffer *sink,
+ size_t *bytes_read, size_t *bytes_written)
+{
+ struct comp_data *cd = comp_get_drvdata(dev);
+ int32_t *src = (int32_t *) source->r_ptr;
+ int32_t *snk = (int32_t *) sink->w_ptr;
+ int nch = dev->params.channels;
+ int frames = cd->param.blk_in;
+ int n;
+ int n_wrap_src;
+ int n_wrap_snk;
+ int n_wrap_min;
+ int n_copy;
+
+ n = frames * nch;
+ while (n > 0) {
+ n_wrap_src = (int32_t *) source->end_addr - src;
+ n_wrap_snk = (int32_t *) sink->end_addr - snk;
+ n_wrap_min = (n_wrap_src < n_wrap_snk) ? n_wrap_src : n_wrap_snk;
+ n_copy = (n < n_wrap_min) ? n : n_wrap_min;
+ memcpy(snk, src, n_copy * sizeof(int32_t));
+
+ /* Update and check both source and destination for wrap */
+ n -= n_copy;
+ src += n_copy;
+ snk += n_copy;
+ src_circ_inc_wrap(&src, source->end_addr, source->size);
+ src_circ_inc_wrap(&snk, sink->end_addr, sink->size);
}
+ *bytes_read = frames * nch * sizeof(int32_t);
+ *bytes_written = frames * nch * sizeof(int32_t);
}
static struct comp_dev *src_new(struct sof_ipc_comp *comp)
@@ -313,7 +329,6 @@ static int src_params(struct comp_dev *dev)
struct comp_data *cd = comp_get_drvdata(dev);
struct comp_buffer *sink;
struct comp_buffer *source;
- struct src_alloc need;
size_t delay_lines_size;
uint32_t source_rate;
uint32_t sink_rate;
@@ -359,7 +374,7 @@ static int src_params(struct comp_dev *dev)
}
/* Allocate needed memory for delay lines */
- err = src_buffer_lengths(&need, source_rate, sink_rate,
+ err = src_buffer_lengths(&cd->param, source_rate, sink_rate,
params->channels, dev->frames, frames_is_for_source);
if (err < 0) {
trace_src_error("sr1");
@@ -370,7 +385,7 @@ static int src_params(struct comp_dev *dev)
return err;
}
- delay_lines_size = sizeof(int32_t) * need.total;
+ delay_lines_size = sizeof(int32_t) * cd->param.total;
if (delay_lines_size == 0) {
trace_src_error("sr2");
return -EINVAL;
@@ -389,17 +404,24 @@ static int src_params(struct comp_dev *dev)
/* Clear all delay lines here */
memset(cd->delay_lines, 0, delay_lines_size);
- cd->scratch_length = need.scratch;
- buffer_start = cd->delay_lines + need.scratch;
+ buffer_start = cd->delay_lines + cd->param.sbuf_length;
/* Initize SRC for actual sample rate */
nch = MIN(params->channels, PLATFORM_MAX_CHANNELS);
for (i = 0; i < nch; i++) {
- n = src_polyphase_init(&cd->src[i], &need, buffer_start);
- buffer_start += need.single_src;
+ n = src_polyphase_init(&cd->src[i], &cd->param, buffer_start);
+ buffer_start += cd->param.single_src;
}
+ /* Reset stage buffer */
+ cd->sbuf_r_ptr = cd->delay_lines;
+ cd->sbuf_w_ptr = cd->delay_lines;
+ cd->sbuf_avail = 0;
+
switch (n) {
+ case 0:
+ cd->src_func = src_copy_s32_default; /* 1:1 fast copy */
+ break;
case 1:
cd->src_func = src_1s_s32_default; /* Simpler 1 stage SRC */
break;
@@ -422,19 +444,13 @@ static int src_params(struct comp_dev *dev)
*/
dev->frame_bytes =
dev->params.sample_container_bytes * dev->params.channels;
- cd->period_bytes = dev->frames * dev->frame_bytes;
/* The downstream buffer must be at least length of blk_out plus
- * dev->frames and an integer multiple of dev->frames. The
+ * a dev->frames and an integer multiple of dev->frames. The
* buffer_set_size will return an error if the required length would
* be too long.
*/
- q = need.blk_out / dev->frames;
- if (q * (int)dev->frames < need.blk_out)
- ++q;
-
- if (q * (int)dev->frames < need.blk_out + (int)dev->frames)
- ++q;
+ q = src_ceil_divide(cd->param.blk_out, (int) dev->frames) + 1;
/* Configure downstream buffer */
sink = list_first_item(&dev->bsink_list, struct comp_buffer,
@@ -452,7 +468,7 @@ static int src_params(struct comp_dev *dev)
/* Check that source buffer has sufficient size */
source = list_first_item(&dev->bsource_list, struct comp_buffer,
sink_list);
- if (source->size < need.blk_in * dev->frame_bytes) {
+ if (source->size < cd->param.blk_in * dev->frame_bytes) {
trace_src_error("eSy");
return -EINVAL;
}
@@ -463,28 +479,8 @@ static int src_params(struct comp_dev *dev)
static int src_ctrl_cmd(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata)
{
- struct comp_data *cd = comp_get_drvdata(dev);
- int i;
-
- switch (cdata->cmd) {
- case SOF_CTRL_CMD_MUTE:
- trace_src("SMu");
- for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
- src_polyphase_mute(&cd->src[i]);
-
- break;
- case SOF_CTRL_CMD_UNMUTE:
- trace_src("SUm");
- for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
- src_polyphase_unmute(&cd->src[i]);
-
- break;
- default:
- trace_src_error("ec1");
- return -EINVAL;
- }
-
- return 0;
+ trace_src_error("ec1");
+ return -EINVAL;
}
/* used to pass standard and bespoke commands (with data) to component */
@@ -513,8 +509,8 @@ static int src_copy(struct comp_dev *dev)
struct comp_buffer *sink;
int need_source;
int need_sink;
- int blk_in;
- int blk_out;
+ size_t consumed = 0;
+ size_t produced = 0;
trace_comp("SRC");
@@ -525,23 +521,29 @@ static int src_copy(struct comp_dev *dev)
source_list);
/* Calculate needed amount of source buffer and sink buffer
- * for one SRC run.
+ * for one SRC run. The blk_in and blk are minimum condition to
+ * call copy. Copy can consume or produce a slightly larger block
+ * with the rates where block sizes are not constant. E.g. for
+ * 1 ms schduling the blocks can be under or above 1 ms when the
+ * SRC interal block size constraint prevents exact 1 ms blocks.
*/
- blk_in = src_polyphase_get_blk_in(&cd->src[0]);
- blk_out = src_polyphase_get_blk_out(&cd->src[0]);
- need_source = blk_in * dev->frame_bytes;
- need_sink = blk_out * dev->frame_bytes;
+ need_source = cd->param.blk_in * dev->frame_bytes;
+ need_sink = cd->param.blk_out * dev->frame_bytes;
- /* Run as many times as buffers allow */
- while (((int) source->avail >= need_source) && ((int) sink->free >= need_sink)) {
+ /* Run SRC function if buffers avail and free allow */
+ if (((int) source->avail >= need_source) && ((int) sink->free >= need_sink)) {
/* Run src */
- cd->src_func(dev, source, sink, blk_in);
+ cd->src_func(dev, source, sink, &consumed, &produced);
- /* calc new free and available */
- comp_update_buffer_consume(source, need_source);
- comp_update_buffer_produce(sink, need_sink);
- }
+ /* Calc new free and available if data was processed. These
+ * functions must not be called with 0 consumed/produced.
+ */
+ if (consumed > 0)
+ comp_update_buffer_consume(source, consumed);
+ if (produced > 0)
+ comp_update_buffer_produce(sink, produced);
+ }
return 0;
}
diff --git a/src/audio/src_core.c b/src/audio/src_core.c
index 8098d87..4ee2efd 100644
--- a/src/audio/src_core.c
+++ b/src/audio/src_core.c
@@ -51,6 +51,18 @@ int sof_rates[SOF_RATES_LENGTH] = {8000, 11025, 12000, 16000, 18900,
22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000, 176400,
192000};
+/* Calculate ceil() for integer division */
+int src_ceil_divide(int a, int b)
+{
+ int c;
+
+ c = a / b;
+ if (c * b < a)
+ c++;
+
+ return c;
+}
+
/* Calculates the needed FIR delay line length */
static int src_fir_delay_length(struct src_stage *s)
{
@@ -62,7 +74,7 @@ static int src_fir_delay_length(struct src_stage *s)
static int src_out_delay_length(struct src_stage *s)
{
- return (s->num_of_subfilters - 1) * s->odm + 1;
+ return 1 + (s->num_of_subfilters - 1) * s->odm;
}
/* Returns index of a matching sample rate */
@@ -108,16 +120,16 @@ int32_t src_output_rates(void)
}
/* Calculates buffers to allocate for a SRC mode */
-int src_buffer_lengths(struct src_alloc *a, int fs_in, int fs_out, int nch,
- int max_frames, int max_frames_is_for_source)
+int src_buffer_lengths(struct src_param *a, int fs_in, int fs_out, int nch,
+ int frames, int frames_is_for_source)
{
- int blk_in;
- int blk_out;
- int k;
- int s1_times;
- int s2_times;
struct src_stage *stage1;
struct src_stage *stage2;
+ int k;
+ int q;
+ int den;
+ int num;
+ int frames2;
a->idx_in = src_find_fs(src_in_fs, NUM_IN_FS, fs_in);
a->idx_out = src_find_fs(src_out_fs, NUM_OUT_FS, fs_out);
@@ -137,46 +149,59 @@ int src_buffer_lengths(struct src_alloc *a, int fs_in, int fs_out, int nch,
a->fir_s1 = src_fir_delay_length(stage1);
a->out_s1 = src_out_delay_length(stage1);
- k = gcd(stage1->blk_out, stage2->blk_in);
- s1_times = stage2->blk_in / k;
- s2_times = s1_times * stage1->blk_out / stage2->blk_in;
- blk_in = s1_times * stage1->blk_in;
- blk_out = s2_times * stage2->blk_out;
-
/* Find out how many additional times the SRC can be executed
while having block size less or equal to max_frames.
*/
- if (max_frames_is_for_source) {
- k = max_frames / blk_in;
+ if (frames_is_for_source) {
+ /* Times that stage1 needs to run to input length of frames */
+ a->stage1_times_max = src_ceil_divide(frames, stage1->blk_in);
+ q = frames / stage1->blk_in;
+ a->stage1_times = MAX(q, 1);
+ a->blk_in = a->stage1_times * stage1->blk_in;
+
+ /* Times that stage2 needs to run */
+ den = stage2->blk_in * stage1->blk_in;
+ num = frames * stage2->blk_out * stage1->blk_out;
+ frames2 = src_ceil_divide(num, den);
+ a->stage2_times_max = src_ceil_divide(frames2, stage2->blk_out);
+ q = frames2 / stage2->blk_out;
+ a->stage2_times = MAX(q, 1);
+ a->blk_out = a->stage2_times * stage2->blk_out;
} else {
- k = max_frames / blk_out;
+ /* Times that stage2 needs to run to output length of frames */
+ a->stage2_times_max = src_ceil_divide(frames, stage2->blk_out);
+ q = frames / stage2->blk_out;
+ a->stage2_times = MAX(q, 1);
+ a->blk_out = a->stage2_times * stage2->blk_out;
+
+ /* Times that stage1 needs to run */
+ num = frames * stage2->blk_in * stage1->blk_in;
+ den = stage2->blk_out * stage1->blk_out;
+ frames2 = src_ceil_divide(num, den);
+ a->stage1_times_max = src_ceil_divide(frames2, stage1->blk_in);
+ q = frames2 / stage1->blk_in;
+ a->stage1_times = MAX(q, 1);
+ a->blk_in = a->stage1_times * stage1->blk_in;
}
- /* Mininum k is 1, when 0 max_frames is less than block length. In
- * that case need to check in src.c that sink/source size is large
- * enough for at least one block.
- */
- if (k < 1)
- k = 1;
-
- a->blk_mult = k;
- a->blk_in = blk_in * k;
- a->blk_out = blk_out * k;
- a->stage1_times = s1_times * k;
- a->stage2_times = s2_times * k;
-
if (stage2->filter_length == 1) {
a->fir_s2 = 0;
a->out_s2 = 0;
- a->scratch = 0;
a->stage2_times = 0;
+ a->stage2_times_max = 0;
+ a->sbuf_length = 0;
} else {
a->fir_s2 = src_fir_delay_length(stage2);
a->out_s2 = src_out_delay_length(stage2);
- a->scratch = stage1->blk_out * s1_times * k;
+ /* 2x is an empirically tested length. Since the sink buffer
+ * capability to receive samples varies a shorter stage 2 output
+ * block will create a peak in internal buffer usage.
+ */
+ a->sbuf_length = 2 * nch * stage1->blk_out * a->stage1_times_max;
}
+
a->single_src = a->fir_s1 + a->fir_s2 + a->out_s1 + a->out_s2;
- a->total = a->scratch + nch * a->single_src;
+ a->total = a->sbuf_length + nch * a->single_src;
return 0;
}
@@ -194,7 +219,7 @@ static void src_state_reset(struct src_state *state)
static int init_stages(
struct src_stage *stage1, struct src_stage *stage2,
- struct polyphase_src *src, struct src_alloc *res,
+ struct polyphase_src *src, struct src_param *p,
int n, int32_t *delay_lines_start)
{
/* Clear FIR state */
@@ -204,29 +229,27 @@ static int init_stages(
src->number_of_stages = n;
src->stage1 = stage1;
src->stage2 = stage2;
+ src->blk_in = p->blk_in;
+ src->blk_out = p->blk_out;
if (n == 1) {
- src->blk_in = stage1->blk_in * res->blk_mult;
- src->blk_out = stage1->blk_out * res->blk_mult;
- src->stage1_times = res->stage1_times;
+ src->stage1_times = p->stage1_times;
src->stage2_times = 0;
if (stage1->blk_out == 0)
return -EINVAL;
} else {
- src->stage1_times = res->stage1_times;
- src->stage2_times = res->stage2_times;
- src->blk_in = res->blk_in;
- src->blk_out = res->blk_out;
+ src->stage1_times = p->stage1_times;
+ src->stage2_times = p->stage2_times;
}
/* Delay line sizes */
- src->state1.fir_delay_size = res->fir_s1;
- src->state1.out_delay_size = res->out_s1;
+ src->state1.fir_delay_size = p->fir_s1;
+ src->state1.out_delay_size = p->out_s1;
src->state1.fir_delay = delay_lines_start;
src->state1.out_delay =
src->state1.fir_delay + src->state1.fir_delay_size;
if (n > 1) {
- src->state2.fir_delay_size = res->fir_s2;
- src->state2.out_delay_size = res->out_s2;
+ src->state2.fir_delay_size = p->fir_s2;
+ src->state2.out_delay_size = p->out_s2;
src->state2.fir_delay =
src->state1.out_delay + src->state1.out_delay_size;
src->state2.out_delay =
@@ -251,7 +274,6 @@ static int init_stages(
}
return 0;
-
}
void src_polyphase_reset(struct polyphase_src *src)
@@ -269,7 +291,7 @@ void src_polyphase_reset(struct polyphase_src *src)
src_state_reset(&src->state2);
}
-int src_polyphase_init(struct polyphase_src *src, struct src_alloc *res,
+int src_polyphase_init(struct polyphase_src *src, struct src_param *p,
int32_t *delay_lines_start)
{
int n_stages;
@@ -277,23 +299,28 @@ int src_polyphase_init(struct polyphase_src *src, struct src_alloc *res,
struct src_stage *stage1;
struct src_stage *stage2;
- if ((res->idx_in < 0) || (res->idx_out < 0)) {
- src->blk_in = res->blk_in;
- src->blk_out = res->blk_out;
+ if ((p->idx_in < 0) || (p->idx_out < 0)) {
+ src->blk_in = p->blk_in;
+ src->blk_out = p->blk_out;
return -EINVAL;
}
/* Get setup for 2 stage conversion */
- stage1 = src_table1[res->idx_out][res->idx_in];
- stage2 = src_table2[res->idx_out][res->idx_in];
- ret = init_stages(stage1, stage2, src, res, 2, delay_lines_start);
+ stage1 = src_table1[p->idx_out][p->idx_in];
+ stage2 = src_table2[p->idx_out][p->idx_in];
+ ret = init_stages(stage1, stage2, src, p, 2, delay_lines_start);
if (ret < 0)
return -EINVAL;
/* Get number of stages used for optimize opportunity. 2nd
* stage length is one if conversion needs only one stage.
+ * If input and output rate is the same return 0 to
+ * use a simple copy function instead of 1 stage FIR with one
+ * tap.
*/
n_stages = (src->stage2->filter_length == 1) ? 1 : 2;
+ if (p->idx_in == p->idx_out)
+ n_stages = 0;
/* If filter length for first stage is zero this is a deleted
* mode from in/out matrix. Computing of such SRC mode needs
@@ -311,14 +338,20 @@ int src_polyphase_init(struct polyphase_src *src, struct src_alloc *res,
static inline void fir_part(int64_t *y, int ntaps, const int16_t c[], int *ic,
int32_t d[], int *id)
{
- int64_t p;
int n;
+ int64_t a = 0;
/* Data is Q1.31, coef is Q1.15, product is Q2.46 */
- for (n = 0; n < ntaps; n++) {
- p = (int64_t) c[(*ic)++] * d[(*id)--];
- *y += p;
+ for (n = 0; n < (ntaps >> 1); n++) {
+ a += (int64_t) c[*ic] * d[*id]
+ + (int64_t) c[*ic + 1] * d[*id - 1];
+ *ic += 2;
+ *id -= 2;
}
+ if (ntaps & 1)
+ a += (int64_t) c[(*ic)++] * d[(*id)--];
+
+ *y += a;
}
#else
@@ -326,15 +359,20 @@ static inline void fir_part(int64_t *y, int ntaps, const int16_t c[], int *ic,
static inline void fir_part(int64_t *y, int ntaps, const int32_t c[], int *ic,
int32_t d[], int *id)
{
- int64_t p;
int n;
+ int64_t a = 0;
/* Data is Q8.24, coef is Q1.23, product is Q9.47 */
- for (n = 0; n < ntaps; n++) {
-
- p = (int64_t) c[(*ic)++] * d[(*id)--];
- *y += p;
+ for (n = 0; n < (ntaps >> 1); n++) {
+ a += (int64_t) c[*ic] * d[*id]
+ + (int64_t) c[*ic + 1] * d[*id - 1];
+ *ic += 2;
+ *id -= 2;
}
+ if (ntaps & 1)
+ a += (int64_t) c[(*ic)++] * d[(*id)--];
+
+ *y += a;
}
#endif
@@ -367,7 +405,7 @@ static inline int32_t fir_filter(
/* Q2.46 -> Q2.31, saturate to Q1.31 */
y = y >> (15 + shift);
- return (int32_t) sat_int32(y);
+ return(int32_t) sat_int32(y);
}
#else
@@ -398,12 +436,14 @@ static inline int32_t fir_filter(
/* Q9.47 -> Q9.24, saturate to Q8.24 */
y = y >> (23 + shift);
- return (int32_t) sat_int32(y);
+ return(int32_t) sat_int32(y);
}
#endif
-void src_polyphase_stage_cir(struct src_stage_prm *s)
+void src_polyphase_stage_cir(struct src_stage_prm * s)
{
+ struct src_state *fir = s->state;
+ struct src_stage *cfg = s->stage;
int n;
int m;
int f;
@@ -412,109 +452,80 @@ void src_polyphase_stage_cir(struct src_stage_prm *s)
int n_wrap_fir;
int n_wrap_buf;
int n_wrap_min;
+ int n_min;
int32_t z;
for (n = 0; n < s->times; n++) {
/* Input data */
- m = s->x_inc * s->stage->blk_in;
+ m = s->x_inc * cfg->blk_in;
while (m > 0) {
- n_wrap_fir =
- (s->state->fir_delay_size - s->state->fir_wi)
+ n_wrap_fir = (fir->fir_delay_size - fir->fir_wi)
* s->x_inc;
n_wrap_buf = s->x_end_addr - s->x_rptr;
n_wrap_min = (n_wrap_fir < n_wrap_buf)
? n_wrap_fir : n_wrap_buf;
- if (m < n_wrap_min) {
- /* No circular wrap need */
- while (m > 0) {
- s->state->fir_delay[s->state->fir_wi++]
- = *s->x_rptr;
- s->x_rptr += s->x_inc;
- m -= s->x_inc;
- }
- } else {
- /* Wrap in n_wrap_min/x_inc samples */
- while (n_wrap_min > 0) {
- s->state->fir_delay[s->state->fir_wi++]
- = *s->x_rptr;
- s->x_rptr += s->x_inc;
- n_wrap_min -= s->x_inc;
- m -= s->x_inc;
- }
- /* Check both */
- if (s->x_rptr >= s->x_end_addr)
- s->x_rptr = (int32_t *)
- ((size_t) s->x_rptr - s->x_size);
- if (s->state->fir_wi
- == s->state->fir_delay_size)
- s->state->fir_wi = 0;
+ n_min = (m < n_wrap_min) ? m : n_wrap_min;
+ while (n_min > 0) {
+ fir->fir_delay[fir->fir_wi++] = *s->x_rptr;
+ s->x_rptr += s->x_inc;
+ n_min -= s->x_inc;
+ m -= s->x_inc;
}
+ /* Check for wrap */
+ src_circ_inc_wrap(&s->x_rptr, s->x_end_addr, s->x_size);
+ if (fir->fir_wi == fir->fir_delay_size)
+ fir->fir_wi = 0;
}
/* Filter */
c = 0;
- r = s->state->fir_wi - s->stage->blk_in
- - (s->stage->num_of_subfilters - 1) * s->stage->idm;
+ r = fir->fir_wi - cfg->blk_in
+ - (cfg->num_of_subfilters - 1) * cfg->idm;
if (r < 0)
- r += s->state->fir_delay_size;
-
- s->state->out_wi = s->state->out_ri;
- for (f = 0; f < s->stage->num_of_subfilters; f++) {
- s->state->fir_ri = r;
- z = fir_filter(s->state, s->stage->coefs, &c,
- s->stage->subfilter_length, s->stage->shift);
- r += s->stage->idm;
- if (r > s->state->fir_delay_size - 1)
- r -= s->state->fir_delay_size;
-
- s->state->out_delay[s->state->out_wi] = z;
- s->state->out_wi += s->stage->odm;
- if (s->state->out_wi > s->state->out_delay_size - 1)
- s->state->out_wi -= s->state->out_delay_size;
+ r += fir->fir_delay_size;
+
+ fir->out_wi = fir->out_ri;
+ for (f = 0; f < cfg->num_of_subfilters; f++) {
+ fir->fir_ri = r;
+ z = fir_filter(fir, cfg->coefs, &c,
+ cfg->subfilter_length, cfg->shift);
+ r += cfg->idm;
+ if (r >= fir->fir_delay_size)
+ r -= fir->fir_delay_size;
+
+ fir->out_delay[fir->out_wi] = z;
+ fir->out_wi += cfg->odm;
+ if (fir->out_wi >= fir->out_delay_size)
+ fir->out_wi -= fir->out_delay_size;
}
/* Output */
- m = s->y_inc * s->stage->num_of_subfilters;
+ m = s->y_inc * cfg->num_of_subfilters;
while (m > 0) {
- n_wrap_fir =
- (s->state->out_delay_size - s->state->out_ri)
+ n_wrap_fir = (fir->out_delay_size - fir->out_ri)
* s->y_inc;
n_wrap_buf = s->y_end_addr - s->y_wptr;
n_wrap_min = (n_wrap_fir < n_wrap_buf)
? n_wrap_fir : n_wrap_buf;
- if (m < n_wrap_min) {
- /* No circular wrap need */
- while (m > 0) {
- *s->y_wptr = s->state->out_delay[
- s->state->out_ri++];
- s->y_wptr += s->y_inc;
- m -= s->y_inc;
- }
- } else {
- /* Wrap in n_wrap_min/y_inc samples */
- while (n_wrap_min > 0) {
- *s->y_wptr = s->state->out_delay[
- s->state->out_ri++];
- s->y_wptr += s->y_inc;
- n_wrap_min -= s->y_inc;
- m -= s->y_inc;
- }
- /* Check both */
- if (s->y_wptr >= s->y_end_addr)
- s->y_wptr =
- (int32_t *)
- ((size_t) s->y_wptr - s->y_size);
-
- if (s->state->out_ri
- == s->state->out_delay_size)
- s->state->out_ri = 0;
+ n_min = (m < n_wrap_min) ? m : n_wrap_min;
+ while (n_min > 0) {
+ *s->y_wptr = fir->out_delay[fir->out_ri++];
+ s->y_wptr += s->y_inc;
+ n_min -= s->y_inc;
+ m -= s->y_inc;
}
+ /* Check wrap */
+ src_circ_inc_wrap(&s->y_wptr, s->y_end_addr, s->y_size);
+ if (fir->out_ri == fir->out_delay_size)
+ fir->out_ri = 0;
}
}
}
-void src_polyphase_stage_cir_s24(struct src_stage_prm *s)
+void src_polyphase_stage_cir_s24(struct src_stage_prm * s)
{
+ struct src_state *fir = s->state;
+ struct src_stage *cfg = s->stage;
int n;
int m;
int f;
@@ -523,113 +534,82 @@ void src_polyphase_stage_cir_s24(struct src_stage_prm *s)
int n_wrap_fir;
int n_wrap_buf;
int n_wrap_min;
- int32_t se;
+ int n_min;
int32_t z;
+ int32_t se;
for (n = 0; n < s->times; n++) {
/* Input data */
- m = s->x_inc * s->stage->blk_in;
+ m = s->x_inc * cfg->blk_in;
while (m > 0) {
- n_wrap_fir =
- (s->state->fir_delay_size - s->state->fir_wi)
+ n_wrap_fir = (fir->fir_delay_size - fir->fir_wi)
* s->x_inc;
n_wrap_buf = s->x_end_addr - s->x_rptr;
n_wrap_min = (n_wrap_fir < n_wrap_buf)
? n_wrap_fir : n_wrap_buf;
- if (m < n_wrap_min) {
- /* No circular wrap need */
- while (m > 0) {
- se = *s->x_rptr << 8;
- s->state->fir_delay[s->state->fir_wi++]
- = se >> 8;
- s->x_rptr += s->x_inc;
- m -= s->x_inc;
- }
- } else {
- /* Wrap in n_wrap_min/x_inc samples */
- while (n_wrap_min > 0) {
- se = *s->x_rptr << 8;
- s->state->fir_delay[s->state->fir_wi++]
- = se >> 8;
- s->x_rptr += s->x_inc;
- n_wrap_min -= s->x_inc;
- m -= s->x_inc;
- }
- /* Check both */
- if (s->x_rptr >= s->x_end_addr)
- s->x_rptr = (int32_t *)
- ((size_t) s->x_rptr - s->x_size);
- if (s->state->fir_wi
- == s->state->fir_delay_size)
- s->state->fir_wi = 0;
+ n_min = (m < n_wrap_min) ? m : n_wrap_min;
+ while (n_min > 0) {
+ se = *s->x_rptr << 8;
+ fir->fir_delay[fir->fir_wi++] = se >> 8;
+ s->x_rptr += s->x_inc;
+ n_min -= s->x_inc;
+ m -= s->x_inc;
}
+ /* Check for wrap */
+ src_circ_inc_wrap(&s->x_rptr, s->x_end_addr, s->x_size);
+ if (fir->fir_wi == fir->fir_delay_size)
+ fir->fir_wi = 0;
}
/* Filter */
c = 0;
- r = s->state->fir_wi - s->stage->blk_in
- - (s->stage->num_of_subfilters - 1) * s->stage->idm;
+ r = fir->fir_wi - cfg->blk_in
+ - (cfg->num_of_subfilters - 1) * cfg->idm;
if (r < 0)
- r += s->state->fir_delay_size;
-
- s->state->out_wi = s->state->out_ri;
- for (f = 0; f < s->stage->num_of_subfilters; f++) {
- s->state->fir_ri = r;
- z = fir_filter(s->state, s->stage->coefs, &c,
- s->stage->subfilter_length, s->stage->shift);
- r += s->stage->idm;
- if (r > s->state->fir_delay_size - 1)
- r -= s->state->fir_delay_size;
-
- s->state->out_delay[s->state->out_wi] = z;
- s->state->out_wi += s->stage->odm;
- if (s->state->out_wi > s->state->out_delay_size - 1)
- s->state->out_wi -= s->state->out_delay_size;
+ r += fir->fir_delay_size;
+
+ fir->out_wi = fir->out_ri;
+ for (f = 0; f < cfg->num_of_subfilters; f++) {
+ fir->fir_ri = r;
+ z = fir_filter(fir, cfg->coefs, &c,
+ cfg->subfilter_length, cfg->shift);
+ r += cfg->idm;
+ if (r >= fir->fir_delay_size)
+ r -= fir->fir_delay_size;
+
+ fir->out_delay[fir->out_wi] = z;
+ fir->out_wi += cfg->odm;
+ if (fir->out_wi >= fir->out_delay_size)
+ fir->out_wi -= fir->out_delay_size;
}
/* Output */
- m = s->y_inc * s->stage->num_of_subfilters;
+ m = s->y_inc * cfg->num_of_subfilters;
while (m > 0) {
- n_wrap_fir =
- (s->state->out_delay_size - s->state->out_ri)
+ n_wrap_fir = (fir->out_delay_size - fir->out_ri)
* s->y_inc;
n_wrap_buf = s->y_end_addr - s->y_wptr;
n_wrap_min = (n_wrap_fir < n_wrap_buf)
? n_wrap_fir : n_wrap_buf;
- if (m < n_wrap_min) {
- /* No circular wrap need */
- while (m > 0) {
- *s->y_wptr = s->state->out_delay[
- s->state->out_ri++];
- s->y_wptr += s->y_inc;
- m -= s->y_inc;
- }
- } else {
- /* Wrap in n_wrap_min/y_inc samples */
- while (n_wrap_min > 0) {
- *s->y_wptr = s->state->out_delay[
- s->state->out_ri++];
- s->y_wptr += s->y_inc;
- n_wrap_min -= s->y_inc;
- m -= s->y_inc;
- }
- /* Check both */
- if (s->y_wptr >= s->y_end_addr)
- s->y_wptr =
- (int32_t *)
- ((size_t) s->y_wptr - s->y_size);
-
- if (s->state->out_ri
- == s->state->out_delay_size)
- s->state->out_ri = 0;
+ n_min = (m < n_wrap_min) ? m : n_wrap_min;
+ while (n_min > 0) {
+ *s->y_wptr = fir->out_delay[fir->out_ri++];
+ s->y_wptr += s->y_inc;
+ n_min -= s->y_inc;
+ m -= s->y_inc;
}
+ /* Check wrap */
+ src_circ_inc_wrap(&s->y_wptr, s->y_end_addr, s->y_size);
+ if (fir->out_ri == fir->out_delay_size)
+ fir->out_ri = 0;
}
}
}
+
#ifdef MODULE_TEST
-void src_print_info(struct polyphase_src *src)
+void src_print_info(struct polyphase_src * src)
{
int n1;
diff --git a/src/audio/src_core.h b/src/audio/src_core.h
index a9f66d4..3859e6f 100644
--- a/src/audio/src_core.h
+++ b/src/audio/src_core.h
@@ -35,19 +35,20 @@
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-struct src_alloc {
+struct src_param {
int fir_s1;
int fir_s2;
int out_s1;
int out_s2;
- int scratch;
+ int sbuf_length;
int single_src;
int total;
- int blk_mult;
int blk_in;
int blk_out;
int stage1_times;
int stage2_times;
+ int stage1_times_max;
+ int stage2_times_max;
int idx_in;
int idx_out;
};
@@ -103,6 +104,18 @@ struct src_stage_prm {
struct src_stage *stage;
};
+static inline void src_circ_inc_wrap(int32_t **ptr, int32_t *end, size_t size)
+{
+ if (*ptr >= end)
+ *ptr = (int32_t *) ((size_t) * ptr - size);
+}
+
+static inline void src_circ_dec_wrap(int32_t **ptr, int32_t *addr, size_t size)
+{
+ if (*ptr < addr)
+ *ptr = (int32_t *) ((size_t) * ptr + size);
+}
+
static inline void src_polyphase_mute(struct polyphase_src *src)
{
src->mute = 1;
@@ -130,7 +143,7 @@ static inline int src_polyphase_get_blk_out(struct polyphase_src *src)
void src_polyphase_reset(struct polyphase_src *src);
-int src_polyphase_init(struct polyphase_src *src, struct src_alloc *res,
+int src_polyphase_init(struct polyphase_src *src, struct src_param *p,
int32_t *delay_lines_start);
int src_polyphase(struct polyphase_src *src, int32_t x[], int32_t y[],
@@ -140,13 +153,15 @@ void src_polyphase_stage_cir(struct src_stage_prm *s);
void src_polyphase_stage_cir_s24(struct src_stage_prm *s);
-int src_buffer_lengths(struct src_alloc *a, int fs_in, int fs_out, int nch,
- int max_frames, int max_frames_is_for_source);
+int src_buffer_lengths(struct src_param *p, int fs_in, int fs_out, int nch,
+ int frames, int frames_is_for_source);
int32_t src_input_rates(void);
int32_t src_output_rates(void);
+int src_ceil_divide(int a, int b);
+
#ifdef MODULE_TEST
void src_print_info(struct polyphase_src *src);
#endif
--
2.11.0
2
1
[Sound-open-firmware] [PATCH] Use 64-bit time instead of 32-bit time for work queue utility.
by yan.wang@linux.intel.com 11 Oct '17
by yan.wang@linux.intel.com 11 Oct '17
11 Oct '17
From: Yan Wang <yan.wang(a)linux.intel.com>
Current timer has been upgraded to 64-bit but work queue utility
still uses 32-bit.
So timer->hitime can't be added rightly because the 64-bit time
is truncated by work queue utility.
"rmbox" will still receive 32-bit timestamp value only and can't
be upgraded to 64-bit timestamp.
Signed-off-by: Yan Wang <yan.wang(a)linux.intel.com>
---
src/audio/dma-trace.c | 2 +-
src/audio/volume.c | 2 +-
src/include/reef/reef.h | 1 +
src/include/reef/wait.h | 4 ++--
src/include/reef/work.h | 4 ++--
src/lib/schedule.c | 2 +-
src/lib/work.c | 30 +++++++++++++++---------------
7 files changed, 23 insertions(+), 22 deletions(-)
diff --git a/src/audio/dma-trace.c b/src/audio/dma-trace.c
index 8fc220e..d725fcf 100644
--- a/src/audio/dma-trace.c
+++ b/src/audio/dma-trace.c
@@ -97,7 +97,7 @@ static void trace_send(struct dma_trace_data *d)
trace_buffer("dts");
}
-static uint32_t trace_work(void *data, uint32_t delay)
+static uint64_t trace_work(void *data, uint64_t delay)
{
struct dma_trace_data *d = (struct dma_trace_data *)data;
diff --git a/src/audio/volume.c b/src/audio/volume.c
index 68c8453..04d1b34 100644
--- a/src/audio/volume.c
+++ b/src/audio/volume.c
@@ -277,7 +277,7 @@ static void vol_update(struct comp_data *cd, uint32_t chan)
}
/* this ramps volume changes over time */
-static uint32_t vol_work(void *data, uint32_t delay)
+static uint64_t vol_work(void *data, uint64_t delay)
{
struct comp_dev *dev = (struct comp_dev *)data;
struct comp_data *cd = comp_get_drvdata(dev);
diff --git a/src/include/reef/reef.h b/src/include/reef/reef.h
index 0cf8261..3450208 100644
--- a/src/include/reef/reef.h
+++ b/src/include/reef/reef.h
@@ -39,6 +39,7 @@ struct ipc;
/* TODO: define for unsigned and short, byte */
#define MAX_INT 0xffffffff
+#define MAX_INT64 0xffffffffffffffff
/* use same syntax as Linux for simplicity */
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
diff --git a/src/include/reef/wait.h b/src/include/reef/wait.h
index c830a75..08fc0b0 100644
--- a/src/include/reef/wait.h
+++ b/src/include/reef/wait.h
@@ -45,7 +45,7 @@
typedef struct {
uint32_t complete;
struct work work;
- uint32_t timeout;
+ uint64_t timeout;
} completion_t;
void arch_wait_for_interrupt(int level);
@@ -57,7 +57,7 @@ static inline void wait_for_interrupt(int level)
tracev_event(TRACE_CLASS_WAIT, "WFX");
}
-static uint32_t _wait_cb(void *data, uint32_t delay)
+static uint64_t _wait_cb(void *data, uint64_t delay)
{
volatile completion_t *wc = (volatile completion_t*)data;
diff --git a/src/include/reef/work.h b/src/include/reef/work.h
index 516f98f..0cdb085 100644
--- a/src/include/reef/work.h
+++ b/src/include/reef/work.h
@@ -45,10 +45,10 @@ struct work_queue;
#define WORK_SYNC (1 << 0) /* work is scheduled synchronously */
struct work {
- uint32_t (*cb)(void*, uint32_t udelay); /* returns reschedule timeout in msecs */
+ uint64_t (*cb)(void*, uint64_t udelay); /* returns reschedule timeout in msecs */
void *cb_data;
struct list_item list;
- uint32_t timeout;
+ uint64_t timeout;
uint32_t pending;
uint32_t flags;
};
diff --git a/src/lib/schedule.c b/src/lib/schedule.c
index 427ca2e..993f94a 100644
--- a/src/lib/schedule.c
+++ b/src/lib/schedule.c
@@ -146,7 +146,7 @@ static inline struct task *edf_get_next(uint64_t current,
}
/* work set in the future when next task can be scheduled */
-static uint32_t sch_work(void *data, uint32_t delay)
+static uint64_t sch_work(void *data, uint64_t delay)
{
tracev_pipe("wrk");
schedule();
diff --git a/src/lib/work.c b/src/lib/work.c
index a267b80..cd21b20 100644
--- a/src/lib/work.c
+++ b/src/lib/work.c
@@ -98,8 +98,8 @@ static int is_work_pending(struct work_queue *queue)
{
struct list_item *wlist;
struct work *work;
- uint32_t win_end;
- uint32_t win_start;
+ uint64_t win_end;
+ uint64_t win_start;
int pending_count = 0;
/* get the current valid window of work */
@@ -131,7 +131,7 @@ static int is_work_pending(struct work_queue *queue)
/* if work has timed out then mark it as pending to run */
if (work->timeout <= win_end ||
- (work->timeout >= win_start && work->timeout < MAX_INT)) {
+ (work->timeout >= win_start && work->timeout < MAX_INT64)) {
work->pending = 1;
pending_count++;
} else {
@@ -144,7 +144,7 @@ static int is_work_pending(struct work_queue *queue)
}
static inline void work_next_timeout(struct work_queue *queue,
- struct work *work, uint32_t reschedule_usecs)
+ struct work *work, uint64_t reschedule_usecs)
{
/* reschedule work */
if (work->flags & WORK_SYNC) {
@@ -162,8 +162,8 @@ static void run_work(struct work_queue *queue, uint32_t *flags)
struct list_item *wlist;
struct list_item *tlist;
struct work *work;
- uint32_t reschedule_usecs;
- uint32_t udelay;
+ uint64_t reschedule_usecs;
+ uint64_t udelay;
/* check each work item in queue for pending */
list_for_item_safe(wlist, tlist, &queue->work) {
@@ -192,9 +192,9 @@ static void run_work(struct work_queue *queue, uint32_t *flags)
}
}
-static inline uint32_t calc_delta_ticks(uint32_t current, uint32_t work)
+static inline uint64_t calc_delta_ticks(uint64_t current, uint64_t work)
{
- uint32_t max = MAX_INT;
+ uint64_t max = MAX_INT64;
/* does work run in next cycle ? */
if (work < current) {
@@ -210,10 +210,10 @@ static void queue_get_next_timeout(struct work_queue *queue)
{
struct list_item *wlist;
struct work *work;
- uint32_t delta = MAX_INT;
- uint32_t current;
- uint32_t d;
- uint32_t ticks;
+ uint64_t delta = MAX_INT64;
+ uint64_t current;
+ uint64_t d;
+ uint64_t ticks;
/* only recalc if work list not empty */
if (list_is_empty(&queue->work)) {
@@ -246,9 +246,9 @@ static void queue_recalc_timers(struct work_queue *queue,
{
struct list_item *wlist;
struct work *work;
- uint32_t delta_ticks;
- uint32_t delta_usecs;
- uint32_t current;
+ uint64_t delta_ticks;
+ uint64_t delta_usecs;
+ uint64_t current;
/* get current time */
current = work_get_timer(queue);
--
2.7.4
2
1
[Sound-open-firmware] [PATCH] Fix the calculation of 64bit timeout.
by yan.wang@linux.intel.com 09 Oct '17
by yan.wang@linux.intel.com 09 Oct '17
09 Oct '17
From: Yan Wang <yan.wang(a)linux.intel.com>
Before the 1st rollover, timer->hitimeout = 0, it will cause
platform_timer_64_handler() set timeout = 1.
So the time irq is forced to be fired at the beginning of rollover.
And the timeout of platform_timer_set() will be invalid and work
queue cannot be fired.
Just set the new hitimeout to timer->hitimeout.
timer->hitime will be added in the next rollover.
It is unnecessary to check timer->hitimout > 0.
Signed-off-by: Yan Wang <yan.wang(a)linux.intel.com>
---
src/platform/baytrail/timer.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/src/platform/baytrail/timer.c b/src/platform/baytrail/timer.c
index 9256dd9..3397ef0 100644
--- a/src/platform/baytrail/timer.c
+++ b/src/platform/baytrail/timer.c
@@ -66,7 +66,7 @@ static void platform_timer_64_handler(void *arg)
}
/* get next timeout value */
- if (timer->hitimeout > 0 && timer->hitimeout == timer->hitime) {
+ if (timer->hitimeout == timer->hitime) {
/* timeout is in this 32 bit period */
timeout = timer->lowtimeout;
} else {
@@ -108,17 +108,13 @@ int platform_timer_set(struct timer *timer, uint64_t ticks)
flags = arch_interrupt_global_disable();
/* same hi 64 bit context as ticks ? */
- if (hitimeout == timer->hitime) {
- /* yes, then set the value for next timeout */
- time = ticks;
- timer->lowtimeout = 0;
- timer->hitimeout = 0;
- } else if (hitimeout < timer->hitime) {
+ if (hitimeout < timer->hitime) {
/* cant be in the past */
arch_interrupt_global_enable(flags);
return -EINVAL;
} else {
/* set for checking at next timeout */
+ time = ticks;
timer->hitimeout = hitimeout;
timer->lowtimeout = ticks;
}
--
2.7.4
2
1
[Sound-open-firmware] [PATCH] component: make sure we can enter the start from paused state
by Liam Girdwood 05 Oct '17
by Liam Girdwood 05 Oct '17
05 Oct '17
Fix state checking to make sure start can be entered after pause.
Signed-off-by: Liam Girdwood <liam.r.girdwood(a)linux.intel.com>
---
src/audio/component.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/audio/component.c b/src/audio/component.c
index ec170c6..80311e3 100644
--- a/src/audio/component.c
+++ b/src/audio/component.c
@@ -122,7 +122,8 @@ int comp_set_state(struct comp_dev *dev, int cmd)
switch (cmd) {
case COMP_CMD_START:
- if (dev->state == COMP_STATE_PREPARE) {
+ if (dev->state == COMP_STATE_PREPARE ||
+ dev->state == COMP_STATE_PAUSED) {
dev->state = COMP_STATE_ACTIVE;
} else {
trace_comp_error("CES");
--
2.11.0
1
1
[Sound-open-firmware] [PATCH] topology: Allows playback and capture pipelines to share same PCM
by Liam Girdwood 02 Oct '17
by Liam Girdwood 02 Oct '17
02 Oct '17
Add support so that different playback and capture pipelines can share
the same host PCM device.
Modify board configs to use PCM0 for playback and capture.
Signed-off-by: Liam Girdwood <liam.r.girdwood(a)linux.intel.com>
---
topology/m4/local.m4 | 62 +++++++++++++++++++--------
topology/reef-apl-nocodec.m4 | 15 ++++---
topology/reef-bdw-rt286.m4 | 15 ++++---
topology/reef-bdw-rt5640.m4 | 15 ++++---
topology/reef-bxt-nocodec.m4 | 13 +++---
topology/reef-byt-nocodec.m4 | 11 +++--
topology/reef-byt-rt5640.m4 | 11 +++--
topology/reef-byt-rt5651.m4 | 11 +++--
topology/reef-cht-nocodec.m4 | 11 +++--
topology/reef-hsw-rt5640.m4 | 15 ++++---
topology/sof/pipe-low-latency-capture.m4 | 28 ++----------
topology/sof/pipe-low-latency-playback.m4 | 29 ++-----------
topology/sof/pipe-passthrough-playback.m4 | 4 +-
topology/sof/pipe-passthrough-src-playback.m4 | 4 +-
topology/sof/pipe-passthrough-vol-playback.m4 | 4 +-
topology/sof/pipe-pcm-media.m4 | 6 +--
16 files changed, 130 insertions(+), 124 deletions(-)
diff --git a/topology/m4/local.m4 b/topology/m4/local.m4
index 50c6b5d..e521267 100644
--- a/topology/m4/local.m4
+++ b/topology/m4/local.m4
@@ -67,12 +67,13 @@ define(`W_BUFFER',
`}')
dnl PCM name)
-define(`N_PCM', `PCM'PCM_ID)
+define(`N_PCMP', `PCM'PCM_ID`P')
+define(`N_PCMC', `PCM'PCM_ID`C')
dnl W_PCM_PLAYBACK(stream, dmac, dmac_chan, periods_sink, periods_source, preload)
dnl PCM platform configuration
define(`W_PCM_PLAYBACK',
-`SectionVendorTuples."'N_PCM($1)`_tuples_w_comp" {'
+`SectionVendorTuples."'N_PCMP($1)`_tuples_w_comp" {'
` tokens "sof_comp_tokens"'
` tuples."word" {'
` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($4)
@@ -80,34 +81,34 @@ define(`W_PCM_PLAYBACK',
` SOF_TKN_COMP_PRELOAD_COUNT' STR($6)
` }'
`}'
-`SectionData."'N_PCM($1)`_data_w_comp" {'
-` tuples "'N_PCM($1)`_tuples_w_comp"'
+`SectionData."'N_PCMP($1)`_data_w_comp" {'
+` tuples "'N_PCMP($1)`_tuples_w_comp"'
`}'
-`SectionVendorTuples."'N_PCM($1)`_tuples" {'
+`SectionVendorTuples."'N_PCMP($1)`_tuples" {'
` tokens "sof_pcm_tokens"'
` tuples."word" {'
` SOF_TKN_PCM_DMAC' STR($2)
` SOF_TKN_PCM_DMAC_CHAN' STR($3)
` }'
`}'
-`SectionData."'N_PCM($1)`_data" {'
-` tuples "'N_PCM($1)`_tuples"'
+`SectionData."'N_PCMP($1)`_data" {'
+` tuples "'N_PCMP($1)`_tuples"'
`}'
-`SectionWidget."'N_PCM`" {'
+`SectionWidget."'N_PCMP`" {'
` index "'PIPELINE_ID`"'
` type "aif_out"'
` no_pm "true"'
` stream_name "'$1`"'
` data ['
-` "'N_PCM($1)`_data"'
-` "'N_PCM($1)`_data_w_comp"'
+` "'N_PCMP($1)`_data"'
+` "'N_PCMP($1)`_data_w_comp"'
` ]'
`}')
dnl W_PCM_PLAYBACK(stream, dmac, dmac_chan, periods_sink, periods_source, preload)
define(`W_PCM_CAPTURE',
-`SectionVendorTuples."'N_PCM($1)`_tuples_w_comp" {'
+`SectionVendorTuples."'N_PCMC($1)`_tuples_w_comp" {'
` tokens "sof_comp_tokens"'
` tuples."word" {'
` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($4)
@@ -115,27 +116,27 @@ define(`W_PCM_CAPTURE',
` SOF_TKN_COMP_PRELOAD_COUNT' STR($6)
` }'
`}'
-`SectionData."'N_PCM($1)`_data_w_comp" {'
-` tuples "'N_PCM($1)`_tuples_w_comp"'
+`SectionData."'N_PCMC($1)`_data_w_comp" {'
+` tuples "'N_PCMC($1)`_tuples_w_comp"'
`}'
-`SectionVendorTuples."'N_PCM($1)`_tuples" {'
+`SectionVendorTuples."'N_PCMC($1)`_tuples" {'
` tokens "sof_pcm_tokens"'
` tuples."word" {'
` SOF_TKN_PCM_DMAC' STR($2)
` SOF_TKN_PCM_DMAC_CHAN' STR($3)
` }'
`}'
-`SectionData."'N_PCM($1)`_data" {'
-` tuples "'N_PCM($1)`_tuples"'
+`SectionData."'N_PCMC($1)`_data" {'
+` tuples "'N_PCMC($1)`_tuples"'
`}'
-`SectionWidget."'N_PCM`" {'
+`SectionWidget."'N_PCMC`" {'
` index "'PIPELINE_ID`"'
` type "aif_out"'
` no_pm "true"'
` stream_name "'$1`"'
` data ['
-` "'N_PCM($1)`_data"'
-` "'N_PCM($1)`_data_w_comp"'
+` "'N_PCMC($1)`_data"'
+` "'N_PCMC($1)`_data_w_comp"'
` ]'
`}')
@@ -478,5 +479,28 @@ define(`COMP_SAMPLE_SIZE',
dnl COMP_BUFFER_SIZE( num_periods, sample_size, channels, fmames)
define(`COMP_BUFFER_SIZE', `eval(`$1 * $2 * $3 * $4')')
+dnl PCM_DUPLEX_ADD(name, pipeline, pcm_id, dai_id, playback, capture)
+define(`PCM_DUPLEX_ADD',
+`SectionPCM.STR($1) {'
+`'
+` index STR($2)'
+`'
+` # used for binding to the PCM'
+` id STR($3)'
+`'
+` dai.STR($1 $3) {'
+` id STR($4)'
+` }'
+`'
+` pcm."capture" {'
+`'
+` capabilities STR($6)'
+` }'
+`'
+` pcm."playback" {'
+`'
+` capabilities STR($5)'
+` }'
+`}')
divert(0) dnl
diff --git a/topology/reef-apl-nocodec.m4 b/topology/reef-apl-nocodec.m4
index 5e497f6..96f28d5 100644
--- a/topology/reef-apl-nocodec.m4
+++ b/topology/reef-apl-nocodec.m4
@@ -36,25 +36,25 @@ PIPELINE_PCM_ADD(sof/pipe-low-latency-playback.m4,
1, 0, 2, s32le,
48, 1000, 0, 0, 0, 1)
-# Low Latency capture pipeline 2 on PCM 1 using max 2 channels of s32le.
+# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s32le.
# Schedule 48 frames per 1000us deadline on core 0 with priority 0
# Use DMAC 0 channel 2 for PCM audio capture data
PIPELINE_PCM_ADD(sof/pipe-low-latency-capture.m4,
- 2, 1, 2, s32le,
+ 2, 0, 2, s32le,
48, 1000, 0, 0, 0, 2)
-# PCM Media Playback pipeline 3 on PCM 2 using max 2 channels of s32le.
+# PCM Media Playback pipeline 3 on PCM 1 using max 2 channels of s32le.
# Schedule 96 frames per 2000us deadline on core 0 with priority 1
# Use DMAC 0 channel 3 for PCM audio playback data
PIPELINE_PCM_ADD(sof/pipe-pcm-media.m4,
- 3, 2, 2, s32le,
+ 3, 1, 2, s32le,
96, 2000, 1, 0, 0, 3)
-# PCM Media Playback pipeline 4 on PCM 3 using max 2 channels of s32le.
+# PCM Media Playback pipeline 4 on PCM 2 using max 2 channels of s32le.
# Schedule 96 frames per 2000us deadline on core 0 with priority 1
# Use DMAC 0 channel 4 for PCM audio playback data
PIPELINE_PCM_ADD(sof/pipe-pcm-media.m4,
- 4, 3, 2, s32le,
+ 4, 2, 2, s32le,
96, 2000, 1, 0, 0, 4)
# Tone Playback pipeline 5 using max 2 channels of s32le.
@@ -97,6 +97,9 @@ DAI_ADD(sof/pipe-dai-capture.m4,
PIPELINE_SINK_2, 2, s24le,
48, 1000, 0, 0)
+# PCM Low Latency
+PCM_DUPLEX_ADD(Low Latency, 6, 0, 0, PIPELINE_PCM_1, PIPELINE_PCM_2)
+
#
# BE configurations - overrides config in ACPI if present
#
diff --git a/topology/reef-bdw-rt286.m4 b/topology/reef-bdw-rt286.m4
index cb11ad6..512efe9 100644
--- a/topology/reef-bdw-rt286.m4
+++ b/topology/reef-bdw-rt286.m4
@@ -36,25 +36,25 @@ PIPELINE_PCM_ADD(sof/pipe-low-latency-playback.m4,
1, 0, 2, s32le,
48, 1000, 0, 0, 0, 1)
-# Low Latency capture pipeline 2 on PCM 1 using max 2 channels of s32le.
+# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s32le.
# Schedule 48 frames per 1000us deadline on core 0 with priority 0
# Use DMAC 0 channel 2 for PCM audio capture data
PIPELINE_PCM_ADD(sof/pipe-low-latency-capture.m4,
- 2, 1, 2, s32le,
+ 2, 0, 2, s32le,
48, 1000, 0, 0, 0, 2)
-# PCM Media Playback pipeline 3 on PCM 2 using max 2 channels of s32le.
+# PCM Media Playback pipeline 3 on PCM 1 using max 2 channels of s32le.
# Schedule 96 frames per 2000us deadline on core 0 with priority 1
# Use DMAC 0 channel 3 for PCM audio playback data
PIPELINE_PCM_ADD(sof/pipe-pcm-media.m4,
- 3, 2, 2, s32le,
+ 3, 1, 2, s32le,
96, 2000, 1, 0, 0, 3)
-# PCM Media Playback pipeline 4 on PCM 3 using max 2 channels of s32le.
+# PCM Media Playback pipeline 4 on PCM 2 using max 2 channels of s32le.
# Schedule 96 frames per 2000us deadline on core 0 with priority 1
# Use DMAC 0 channel 4 for PCM audio playback data
PIPELINE_PCM_ADD(sof/pipe-pcm-media.m4,
- 4, 3, 2, s32le,
+ 4, 2, 2, s32le,
96, 2000, 1, 0, 0, 4)
# Tone Playback pipeline 5 using max 2 channels of s32le.
@@ -97,6 +97,9 @@ DAI_ADD(sof/pipe-dai-capture.m4,
PIPELINE_SINK_2, 2, s24le,
48, 1000, 0, 0)
+# PCM Low Latency
+PCM_DUPLEX_ADD(Low Latency, 6, 0, 0, PIPELINE_PCM_1, PIPELINE_PCM_2)
+
#
# BE configurations - overrides config in ACPI if present
#
diff --git a/topology/reef-bdw-rt5640.m4 b/topology/reef-bdw-rt5640.m4
index b3c19c2..5e259a6 100644
--- a/topology/reef-bdw-rt5640.m4
+++ b/topology/reef-bdw-rt5640.m4
@@ -36,25 +36,25 @@ PIPELINE_PCM_ADD(sof/pipe-low-latency-playback.m4,
1, 0, 2, s32le,
48, 1000, 0, 0, 0, 1)
-# Low Latency capture pipeline 2 on PCM 1 using max 2 channels of s32le.
+# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s32le.
# Schedule 48 frames per 1000us deadline on core 0 with priority 0
# Use DMAC 0 channel 2 for PCM audio capture data
PIPELINE_PCM_ADD(sof/pipe-low-latency-capture.m4,
- 2, 1, 2, s32le,
+ 2, 0, 2, s32le,
48, 1000, 0, 0, 0, 2)
-# PCM Media Playback pipeline 3 on PCM 2 using max 2 channels of s32le.
+# PCM Media Playback pipeline 3 on PCM 1 using max 2 channels of s32le.
# Schedule 96 frames per 2000us deadline on core 0 with priority 1
# Use DMAC 0 channel 3 for PCM audio playback data
PIPELINE_PCM_ADD(sof/pipe-pcm-media.m4,
- 3, 2, 2, s32le,
+ 3, 1, 2, s32le,
96, 2000, 1, 0, 0, 3)
-# PCM Media Playback pipeline 4 on PCM 3 using max 2 channels of s32le.
+# PCM Media Playback pipeline 4 on PCM 2 using max 2 channels of s32le.
# Schedule 96 frames per 2000us deadline on core 0 with priority 1
# Use DMAC 0 channel 4 for PCM audio playback data
PIPELINE_PCM_ADD(sof/pipe-pcm-media.m4,
- 4, 3, 2, s32le,
+ 4, 2, 2, s32le,
96, 2000, 1, 0, 0, 4)
# Tone Playback pipeline 5 using max 2 channels of s32le.
@@ -97,6 +97,9 @@ DAI_ADD(sof/pipe-dai-capture.m4,
PIPELINE_SINK_2, 2, s24le,
48, 1000, 0, 0)
+# PCM Low Latency
+PCM_DUPLEX_ADD(Low Latency, 6, 0, 0, PIPELINE_PCM_1, PIPELINE_PCM_2)
+
#
# BE configurations - overrides config in ACPI if present
#
diff --git a/topology/reef-bxt-nocodec.m4 b/topology/reef-bxt-nocodec.m4
index 58bc6f6..e3c45c9 100644
--- a/topology/reef-bxt-nocodec.m4
+++ b/topology/reef-bxt-nocodec.m4
@@ -36,21 +36,21 @@ PIPELINE_PCM_ADD(sof/pipe-low-latency-playback.m4,
1, 0, 2, s32le,
48, 1000, 0, 0, 0, 1)
-# Low Latency capture pipeline 2 on PCM 1 using max 2 channels of s32le.
+# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s32le.
# Schedule 48 frames per 1000us deadline on core 0 with priority 0
# Use DMAC 0 channel 2 for PCM audio capture data
PIPELINE_PCM_ADD(sof/pipe-low-latency-capture.m4,
- 2, 1, 2, s32le,
+ 2, 0, 2, s32le,
48, 1000, 0, 0, 0, 2)
-# PCM Media Playback pipeline 3 on PCM 2 using max 2 channels of s32le.
+# PCM Media Playback pipeline 3 on PCM 1 using max 2 channels of s32le.
# Schedule 192 frames per 4000us deadline on core 0 with priority 1
# Use DMAC 0 channel 3 for PCM audio playback data
PIPELINE_PCM_ADD(sof/pipe-pcm-media.m4,
- 3, 2, 2, s32le,
+ 3, 1, 2, s32le,
192, 4000, 1, 0, 0, 3)
-# PCM Media Playback pipeline 4 on PCM 3 using max 2 channels of s32le.
+# PCM Media Playback pipeline 4 on PCM 2 using max 2 channels of s32le.
# Schedule 192 frames per 4000us deadline on core 0 with priority 1
# Use DMAC 0 channel 3 for PCM audio playback data
PIPELINE_PCM_ADD(sof/pipe-pcm-media.m4,
@@ -97,6 +97,9 @@ DAI_ADD(sof/pipe-dai-capture.m4,
PIPELINE_SINK_2, 2, s24le,
48, 1000, 0, 0)
+# PCM Low Latency
+PCM_DUPLEX_ADD(Low Latency, 6, 0, 0, PIPELINE_PCM_1, PIPELINE_PCM_2)
+
#
# BE configurations - overrides config in ACPI if present
#
diff --git a/topology/reef-byt-nocodec.m4 b/topology/reef-byt-nocodec.m4
index 5f6cd1d..3db415d 100644
--- a/topology/reef-byt-nocodec.m4
+++ b/topology/reef-byt-nocodec.m4
@@ -34,18 +34,18 @@ PIPELINE_PCM_ADD(sof/pipe-low-latency-playback.m4,
1, 0, 2, s32le,
48, 1000, 0, 0, 0, 1)
-# Low Latency capture pipeline 2 on PCM 1 using max 2 channels of s32le.
+# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s32le.
# Schedule 48 frames per 1000us deadline on core 0 with priority 0
# Use DMAC 0 channel 2 for PCM audio capture data
PIPELINE_PCM_ADD(sof/pipe-low-latency-capture.m4,
- 2, 1, 2, s32le,
+ 2, 0, 2, s32le,
48, 1000, 0, 0, 0, 2)
-# PCM Media Playback pipeline 3 on PCM 2 using max 2 channels of s32le.
+# PCM Media Playback pipeline 3 on PCM 1 using max 2 channels of s32le.
# Schedule 192 frames per 4000us deadline on core 0 with priority 1
# Use DMAC 0 channel 3 for PCM audio playback data
PIPELINE_PCM_ADD(sof/pipe-pcm-media.m4,
- 3, 2, 2, s32le,
+ 3, 1, 2, s32le,
192, 4000, 1, 0, 0, 3)
# Tone Playback pipeline 5 using max 2 channels of s32le.
@@ -86,6 +86,9 @@ DAI_ADD(sof/pipe-dai-capture.m4,
PIPELINE_SINK_2, 2, s24le,
48, 1000, 0, 0)
+# PCM Low Latency
+PCM_DUPLEX_ADD(Low Latency, 6, 0, 0, PIPELINE_PCM_1, PIPELINE_PCM_2)
+
#
# BE configurations - overrides config in ACPI if present
#
diff --git a/topology/reef-byt-rt5640.m4 b/topology/reef-byt-rt5640.m4
index c5e8b52..1e9bb5f 100644
--- a/topology/reef-byt-rt5640.m4
+++ b/topology/reef-byt-rt5640.m4
@@ -34,18 +34,18 @@ PIPELINE_PCM_ADD(sof/pipe-low-latency-playback.m4,
1, 0, 2, s32le,
48, 1000, 0, 0, 0, 1)
-# Low Latency capture pipeline 2 on PCM 1 using max 2 channels of s32le.
+# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s32le.
# Schedule 48 frames per 1000us deadline on core 0 with priority 0
# Use DMAC 0 channel 2 for PCM audio capture data
PIPELINE_PCM_ADD(sof/pipe-low-latency-capture.m4,
- 2, 1, 2, s32le,
+ 2, 0, 2, s32le,
48, 1000, 0, 0, 0, 2)
-# PCM Media Playback pipeline 3 on PCM 2 using max 2 channels of s32le.
+# PCM Media Playback pipeline 3 on PCM 1 using max 2 channels of s32le.
# Schedule 192 frames per 4000us deadline on core 0 with priority 1
# Use DMAC 0 channel 3 for PCM audio playback data
PIPELINE_PCM_ADD(sof/pipe-pcm-media.m4,
- 3, 2, 2, s32le,
+ 3, 1, 2, s32le,
192, 4000, 1, 0, 0, 3)
# Tone Playback pipeline 5 using max 2 channels of s32le.
@@ -86,6 +86,9 @@ DAI_ADD(sof/pipe-dai-capture.m4,
PIPELINE_SINK_2, 2, s24le,
48, 1000, 0, 0)
+# PCM Low Latency
+PCM_DUPLEX_ADD(Low Latency, 6, 0, 0, PIPELINE_PCM_1, PIPELINE_PCM_2)
+
#
# BE configurations - overrides config in ACPI if present
#
diff --git a/topology/reef-byt-rt5651.m4 b/topology/reef-byt-rt5651.m4
index e335d66..0867f91 100644
--- a/topology/reef-byt-rt5651.m4
+++ b/topology/reef-byt-rt5651.m4
@@ -34,18 +34,18 @@ PIPELINE_PCM_ADD(sof/pipe-low-latency-playback.m4,
1, 0, 2, s32le,
48, 1000, 0, 0, 0, 1)
-# Low Latency capture pipeline 2 on PCM 1 using max 2 channels of s32le.
+# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s32le.
# Schedule 48 frames per 1000us deadline on core 0 with priority 0
# Use DMAC 0 channel 2 for PCM audio capture data
PIPELINE_PCM_ADD(sof/pipe-low-latency-capture.m4,
- 2, 1, 2, s32le,
+ 2, 0, 2, s32le,
48, 1000, 0, 0, 0, 2)
-# PCM Media Playback pipeline 3 on PCM 2 using max 2 channels of s32le.
+# PCM Media Playback pipeline 3 on PCM 1 using max 2 channels of s32le.
# Schedule 192 frames per 4000us deadline on core 0 with priority 1
# Use DMAC 0 channel 3 for PCM audio playback data
PIPELINE_PCM_ADD(sof/pipe-pcm-media.m4,
- 3, 2, 2, s32le,
+ 3, 1, 2, s32le,
192, 4000, 1, 0, 0, 3)
# Tone Playback pipeline 5 using max 2 channels of s32le.
@@ -86,6 +86,9 @@ DAI_ADD(sof/pipe-dai-capture.m4,
PIPELINE_SINK_2, 2, s24le,
48, 1000, 0, 0)
+# PCM Low Latency
+PCM_DUPLEX_ADD(Low Latency, 3, 0, 0, PIPELINE_PCM_1, PIPELINE_PCM_2)
+
#
# BE configurations - overrides config in ACPI if present
#
diff --git a/topology/reef-cht-nocodec.m4 b/topology/reef-cht-nocodec.m4
index ddeb71e..195ae5c 100644
--- a/topology/reef-cht-nocodec.m4
+++ b/topology/reef-cht-nocodec.m4
@@ -34,18 +34,18 @@ PIPELINE_PCM_ADD(sof/pipe-low-latency-playback.m4,
1, 0, 2, s32le,
48, 1000, 0, 0, 0, 1)
-# Low Latency capture pipeline 2 on PCM 1 using max 2 channels of s32le.
+# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s32le.
# Schedule 48 frames per 1000us deadline on core 0 with priority 0
# Use DMAC 0 channel 2 for PCM audio capture data
PIPELINE_PCM_ADD(sof/pipe-low-latency-capture.m4,
- 2, 1, 2, s32le,
+ 2, 0, 2, s32le,
48, 1000, 0, 0, 0, 2)
-# PCM Media Playback pipeline 3 on PCM 2 using max 2 channels of s32le.
+# PCM Media Playback pipeline 3 on PCM 1 using max 2 channels of s32le.
# Schedule 192 frames per 4000us deadline on core 0 with priority 1
# Use DMAC 0 channel 3 for PCM audio playback data
PIPELINE_PCM_ADD(sof/pipe-pcm-media.m4,
- 3, 2, 2, s32le,
+ 3, 1, 2, s32le,
192, 4000, 1, 0, 0, 3)
# Tone Playback pipeline 5 using max 2 channels of s32le.
@@ -86,6 +86,9 @@ DAI_ADD(sof/pipe-dai-capture.m4,
PIPELINE_SINK_2, 2, s24le,
48, 1000, 0, 0)
+# PCM Low Latency
+PCM_DUPLEX_ADD(Low Latency, 6, 0, 0, PIPELINE_PCM_1, PIPELINE_PCM_2)
+
#
# BE configurations - overrides config in ACPI if present
#
diff --git a/topology/reef-hsw-rt5640.m4 b/topology/reef-hsw-rt5640.m4
index efd815b..1b06828 100644
--- a/topology/reef-hsw-rt5640.m4
+++ b/topology/reef-hsw-rt5640.m4
@@ -36,25 +36,25 @@ PIPELINE_PCM_ADD(sof/pipe-low-latency-playback.m4,
1, 0, 2, s32le,
48, 1000, 0, 0, 0, 1)
-# Low Latency capture pipeline 2 on PCM 1 using max 2 channels of s32le.
+# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s32le.
# Schedule 48 frames per 1000us deadline on core 0 with priority 0
# Use DMAC 0 channel 2 for PCM audio capture data
PIPELINE_PCM_ADD(sof/pipe-low-latency-capture.m4,
- 2, 1, 2, s32le,
+ 2, 0, 2, s32le,
48, 1000, 0, 0, 0, 2)
-# PCM Media Playback pipeline 3 on PCM 2 using max 2 channels of s32le.
+# PCM Media Playback pipeline 3 on PCM 1 using max 2 channels of s32le.
# Schedule 192 frames per 4000us deadline on core 0 with priority 1
# Use DMAC 0 channel 3 for PCM audio playback data
PIPELINE_PCM_ADD(sof/pipe-pcm-media.m4,
- 3, 2, 2, s32le,
+ 3, 1, 2, s32le,
192, 4000, 1, 0, 0, 3)
-# PCM Media Playback pipeline 4 on PCM 3 using max 2 channels of s32le.
+# PCM Media Playback pipeline 4 on PCM 2 using max 2 channels of s32le.
# Schedule 192 frames per 4000us deadline on core 0 with priority 1
# Use DMAC 0 channel 3 for PCM audio playback data
PIPELINE_PCM_ADD(sof/pipe-pcm-media.m4,
- 3, 2, 2, s32le,
+ 4, 2, 2, s32le,
192, 4000, 1, 0, 0, 4)
# Tone Playback pipeline 5 using max 2 channels of s32le.
@@ -97,6 +97,9 @@ DAI_ADD(sof/pipe-dai-capture.m4,
PIPELINE_SINK_2, 2, s24le,
48, 1000, 0, 0)
+# PCM Low Latency
+PCM_DUPLEX_ADD(Low Latency, 6, 0, 0, PIPELINE_PCM_1, PIPELINE_PCM_2)
+
#
# BE configurations - overrides config in ACPI if present
#
diff --git a/topology/sof/pipe-low-latency-capture.m4 b/topology/sof/pipe-low-latency-capture.m4
index 22df648..0c989a7 100644
--- a/topology/sof/pipe-low-latency-capture.m4
+++ b/topology/sof/pipe-low-latency-capture.m4
@@ -65,8 +65,8 @@ SectionGraph."pipe-ll-capture-PIPELINE_ID" {
index STR(PIPELINE_ID)
lines [
- dapm(Low Latency Capture PCM_ID, N_PCM)
- dapm(N_PCM, N_BUFFER(1))
+ dapm(Low Latency Capture PCM_ID, N_PCMC)
+ dapm(N_PCMC, N_BUFFER(1))
dapm(N_BUFFER(1), N_PGA(0))
dapm(N_PGA(0), N_BUFFER(0))
]
@@ -76,12 +76,7 @@ SectionGraph."pipe-ll-capture-PIPELINE_ID" {
# Pipeline Source and Sinks
#
indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(0))
-
-#
-# Pipeline Configuration.
-#
-
-#W_PIPELINE(N_PGA(0), SCHEDULE_DEADLINE, SCHEDULE_PRIORITY, SCHEDULE_FRAMES, SCHEDULE_CORE, pipe_ll_schedule_plat)
+indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Low Latency Capture PCM_ID)
#
# PCM Configuration
@@ -102,20 +97,3 @@ SectionPCMCapabilities.STR(Low Latency Capture PCM_ID) {
buffer_size_max "65536"
}
-# PCM Low Latency Capture
-SectionPCM.STR(PCM PCM_ID) {
-
- index STR(PIPELINE_ID)
-
- # used for binding to the PCM
- id STR(PCM_ID)
-
- dai.STR(Low Latency Capture PCM_ID) {
- id STR(PCM_ID)
- }
-
- pcm."capture" {
-
- capabilities STR(Low Latency Capture PCM_ID)
- }
-}
diff --git a/topology/sof/pipe-low-latency-playback.m4 b/topology/sof/pipe-low-latency-playback.m4
index c29165e..cd04ccf 100644
--- a/topology/sof/pipe-low-latency-playback.m4
+++ b/topology/sof/pipe-low-latency-playback.m4
@@ -125,8 +125,8 @@ SectionGraph."pipe-ll-playback-PIPELINE_ID" {
index STR(PIPELINE_ID)
lines [
- dapm(N_PCM, Low Latency Playback PCM_ID)
- dapm(N_BUFFER(0), N_PCM)
+ dapm(N_PCMP, Low Latency Playback PCM_ID)
+ dapm(N_BUFFER(0), N_PCMP)
dapm(N_PGA(0), N_BUFFER(0))
dapm(N_BUFFER(1), N_PGA(0))
dapm(N_MIXER(0), N_BUFFER(1))
@@ -141,12 +141,7 @@ SectionGraph."pipe-ll-playback-PIPELINE_ID" {
#
indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(3))
indir(`define', concat(`PIPELINE_MIXER_', PIPELINE_ID), N_MIXER(0))
-
-#
-# Pipeline Configuration.
-#
-
-#W_PIPELINE(N_PGA(1), SCHEDULE_DEADLINE, SCHEDULE_PRIORITY, SCHEDULE_FRAMES, SCHEDULE_CORE, pipe_ll_schedule_plat)
+indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Low Latency Playback PCM_ID)
#
# PCM Configuration
@@ -168,21 +163,3 @@ SectionPCMCapabilities.STR(Low Latency Playback PCM_ID) {
buffer_size_max "65536"
}
-# PCM Low Latency Playback
-SectionPCM.STR(PCM PCM_ID) {
-
- index STR(PIPELINE_ID)
-
- # used for binding to the PCM
- id STR(PCM_ID)
-
- dai.STR(Low Latency Playback PCM_ID) {
- id STR(PCM_ID)
- }
-
- # Playback and Capture Configuration
- pcm."playback" {
-
- capabilities STR(Low Latency Playback PCM_ID)
- }
-}
diff --git a/topology/sof/pipe-passthrough-playback.m4 b/topology/sof/pipe-passthrough-playback.m4
index 46ed949..4e6e705 100644
--- a/topology/sof/pipe-passthrough-playback.m4
+++ b/topology/sof/pipe-passthrough-playback.m4
@@ -39,8 +39,8 @@ SectionGraph."pipe-pass-playback-PIPELINE_ID" {
index STR(PIPELINE_ID)
lines [
- dapm(N_PCM, Passthrough Playback PCM_ID)
- dapm(N_BUFFER(0), N_PCM)
+ dapm(N_PCMP, Passthrough Playback PCM_ID)
+ dapm(N_BUFFER(0), N_PCMP)
dapm(N_DAI_OUT, N_BUFFER(0))
]
}
diff --git a/topology/sof/pipe-passthrough-src-playback.m4 b/topology/sof/pipe-passthrough-src-playback.m4
index 0ffc2a4..3cadaf2 100644
--- a/topology/sof/pipe-passthrough-src-playback.m4
+++ b/topology/sof/pipe-passthrough-src-playback.m4
@@ -62,8 +62,8 @@ SectionGraph."pipe-pass-src-playback-PIPELINE_ID" {
index STR(PIPELINE_ID)
lines [
- dapm(N_PCM, Passthrough Playback PCM_ID)
- dapm(N_BUFFER(0), N_PCM)
+ dapm(N_PCMP, Passthrough Playback PCM_ID)
+ dapm(N_BUFFER(0), N_PCMP)
dapm(N_SRC(0), N_BUFFER(0))
dapm(N_BUFFER(1), N_SRC(0))
dapm(N_DAI_OUT, N_BUFFER(1))
diff --git a/topology/sof/pipe-passthrough-vol-playback.m4 b/topology/sof/pipe-passthrough-vol-playback.m4
index ffc9000..f0e39e8 100644
--- a/topology/sof/pipe-passthrough-vol-playback.m4
+++ b/topology/sof/pipe-passthrough-vol-playback.m4
@@ -76,8 +76,8 @@ SectionGraph."pipe-pass-vol-playback-PIPELINE_ID" {
index STR(PIPELINE_ID)
lines [
- dapm(N_PCM, Passthrough Playback PCM_ID)
- dapm(N_BUFFER(0), N_PCM)
+ dapm(N_PCMP, Passthrough Playback PCM_ID)
+ dapm(N_BUFFER(0), N_PCMP)
dapm(N_PGA(0), N_BUFFER(0))
dapm(N_BUFFER(1), N_PGA(0))
dapm(N_DAI_OUT, N_BUFFER(1))
diff --git a/topology/sof/pipe-pcm-media.m4 b/topology/sof/pipe-pcm-media.m4
index b04b353..7bfb35a 100644
--- a/topology/sof/pipe-pcm-media.m4
+++ b/topology/sof/pipe-pcm-media.m4
@@ -93,8 +93,8 @@ SectionGraph."pipe-media-PIPELINE_ID" {
index STR(PIPELINE_ID)
lines [
- dapm(N_PCM, Media Playback PCM_ID)
- dapm(N_BUFFER(0), N_PCM)
+ dapm(N_PCMP, Media Playback PCM_ID)
+ dapm(N_BUFFER(0), N_PCMP)
dapm(N_PGA(0), N_BUFFER(0))
dapm(N_BUFFER(1), N_PGA(0))
dapm(N_SRC(0), N_BUFFER(1))
@@ -134,7 +134,7 @@ SectionPCMCapabilities.STR(Media Playback PCM_ID) {
}
# PCM Low Latency Playback and Capture
-SectionPCM.STR(PCM PCM_ID) {
+SectionPCM.STR(Media Playback PCM_ID) {
index STR(PIPELINE_ID)
--
1.9.1
1
0