[Sound-open-firmware] [PATCH 1/4] SRC: IPC updates and fixes v2
SRC updates sink and downstream pipeline PCM rate, period_count and period_bytes in src_params() according to received out_rate via IPC. Also the use of incorrect alloc_size is replaced by ipc_buffer.size.
Signed-off-by: Seppo Ingalsuo seppo.ingalsuo@linux.intel.com --- src/audio/src.c | 90 ++++++++++++++++++++++++----------------- src/include/reef/audio/buffer.h | 8 ++-- src/include/uapi/ipc.h | 1 + 3 files changed, 57 insertions(+), 42 deletions(-)
diff --git a/src/audio/src.c b/src/audio/src.c index c338220..f1f4b86 100644 --- a/src/audio/src.c +++ b/src/audio/src.c @@ -56,9 +56,13 @@ /* src component private data */ struct comp_data { struct polyphase_src src[PLATFORM_MAX_CHANNELS]; + /* Next two elements must be kept in this order since + * the end of pcm_params is a flexible array. + */ + struct sof_ipc_pcm_params pcm_params; + enum sof_ipc_chmap channel_map[PLATFORM_MAX_CHANNELS]; int32_t *delay_lines; int scratch_length; - //int32_t z[STAGE_BUF_SIZE]; void (*src_func)(struct comp_dev *dev, struct comp_buffer *source, struct comp_buffer *sink, @@ -155,7 +159,7 @@ static void src_2s_s32_default(struct comp_dev *dev,
s1.times = n_times1; s1.x_end_addr = source->end_addr; - s1.x_size = source->alloc_size; + s1.x_size = source->ipc_buffer.size; s1.x_inc = nch; s1.y_end_addr = &cd->delay_lines[cd->scratch_length]; s1.y_size = STAGE_BUF_SIZE * sizeof(int32_t); @@ -166,7 +170,7 @@ static void src_2s_s32_default(struct comp_dev *dev, s2.x_size = STAGE_BUF_SIZE * sizeof(int32_t); s2.x_inc = 1; s2.y_end_addr = sink->end_addr; - s2.y_size = sink->alloc_size; + s2.y_size = sink->ipc_buffer.size; s2.y_inc = nch;
s1.x_rptr = src + nch - 1; @@ -227,10 +231,10 @@ static void src_1s_s32_default(struct comp_dev *dev,
s1.times = n_times; s1.x_end_addr = source->end_addr; - s1.x_size = source->alloc_size; + s1.x_size = source->ipc_buffer.size; s1.x_inc = nch; s1.y_end_addr = sink->end_addr; - s1.y_size = sink->alloc_size; + s1.y_size = sink->ipc_buffer.size; s1.y_inc = nch; s1.x_rptr = src + nch - 1; s1.y_wptr = dest + nch - 1; @@ -263,7 +267,7 @@ static struct comp_dev *src_new(struct sof_ipc_comp *comp) { struct comp_dev *dev; struct sof_ipc_comp_src *src; - struct sof_ipc_comp_src *ipc_src = (struct sof_ipc_comp_src *)comp; + struct sof_ipc_comp_src *ipc_src = (struct sof_ipc_comp_src *) comp; struct comp_data *cd; int i;
@@ -274,7 +278,7 @@ static struct comp_dev *src_new(struct sof_ipc_comp *comp) if (dev == NULL) return NULL;
- src = (struct sof_ipc_comp_src *)&dev->comp; + src = (struct sof_ipc_comp_src *) &dev->comp; memcpy(src, ipc_src, sizeof(struct sof_ipc_comp_src));
cd = rmalloc(RZONE_RUNTIME, RFLAGS_NONE, sizeof(*cd)); @@ -317,6 +321,7 @@ static int src_params(struct comp_dev *dev, struct stream_params *params) int32_t *buffer_start; int n = 0; struct comp_data *cd = comp_get_drvdata(dev); + struct sof_ipc_comp_src *src = (struct sof_ipc_comp_src *) &dev->comp;
trace_src("SPa");
@@ -325,23 +330,43 @@ static int src_params(struct comp_dev *dev, struct stream_params *params) || (params->pcm->frame_fmt != SOF_IPC_FRAME_S32_LE)) return -EINVAL;
- /* No data transformation */ - comp_set_sink_params(dev, params); - - /* Allocate needed memory for delay lines */ source = list_first_item(&dev->bsource_list, struct comp_buffer, sink_list); sink = list_first_item(&dev->bsink_list, struct comp_buffer, source_list); - src_buffer_lengths(&need, source->params.pcm->rate, - sink->params.pcm->rate, source->params.pcm->channels); + + /* Copy PCM stream parameters and the channel map array */ + memcpy(&cd->pcm_params, &(*params->pcm), + sizeof(struct sof_ipc_pcm_params)); + for (i = 0; i < params->pcm->channels; i++) + cd->pcm_params.channel_map[i] = params->pcm->channel_map[i]; + + /* Point sink stream parameters to copy */ + sink->params.pcm = &cd->pcm_params; + + /* Stored IPC from src_new() contains the output rate for sink, + * set the new rate for sink. + */ + sink->params.pcm->rate = src->out_rate; + + /* Adjust sink buffer parameters to match fs_out/fs_in */ + sink->params.pcm->period_count = sink->params.pcm->period_count + * sink->params.pcm->rate / source->params.pcm->rate; + sink->params.pcm->period_bytes = sink->params.pcm->period_bytes + * sink->params.pcm->rate / source->params.pcm->rate; + + /* Allocate needed memory for delay lines */ + if (src_buffer_lengths(&need, source->params.pcm->rate, + sink->params.pcm->rate, source->params.pcm->channels) < 0) + return -EINVAL; + delay_lines_size = sizeof(int32_t) * need.total; if (cd->delay_lines != NULL) rfree(cd->delay_lines);
cd->delay_lines = rmalloc(RZONE_RUNTIME, RFLAGS_NONE, delay_lines_size); if (cd->delay_lines == NULL) - return -EINVAL; + return -ENOMEM;
/* Clear all delay lines here */ memset(cd->delay_lines, 0, delay_lines_size); @@ -369,19 +394,20 @@ static int src_params(struct comp_dev *dev, struct stream_params *params) */ trace_src("SFa"); cd->src_func = fallback_s32; - return(-EINVAL); - break; + rfree(cd->delay_lines); + return -EINVAL; }
/* Check that src blk_in and blk_out are less than params.period_frames. * Return an error if the period is too short. */ - if (src_polyphase_get_blk_in(&cd->src[0]) > source->params.pcm->period_count) - return(-EINVAL); - - if (src_polyphase_get_blk_out(&cd->src[0]) > sink->params.pcm->period_count) - return(-EINVAL); + if (src_polyphase_get_blk_in(&cd->src[0]) + > source->params.pcm->period_count) + return -EINVAL;
+ if (src_polyphase_get_blk_out(&cd->src[0]) + > sink->params.pcm->period_count) + return -EINVAL;
return 0; } @@ -453,7 +479,8 @@ static int src_copy(struct comp_dev *dev) struct comp_buffer *sink; uint32_t frames_source; uint32_t frames_sink; - int need_source, need_sink, min_frames; + int need_source, need_sink; + // int min_frames;
trace_comp("SRC");
@@ -464,25 +491,12 @@ static int src_copy(struct comp_dev *dev) source_list);
/* Check that source has enough frames available and sink enough - * frames free. + * frames free. Increase tried period_count if not sufficient to run. */ frames_source = source->params.pcm->period_count; frames_sink = sink->params.pcm->period_count; - min_frames = src_polyphase_get_blk_in(&cd->src[0]); - if (frames_source > min_frames) - need_source = frames_source * source->params.pcm->frame_size; - else { - frames_source = min_frames; - need_source = min_frames * source->params.pcm->frame_size; - } - - min_frames = src_polyphase_get_blk_out(&cd->src[0]); - if (frames_sink > min_frames) - need_sink = frames_sink * sink->params.pcm->frame_size; - else { - frames_sink = min_frames; - need_sink = min_frames * sink->params.pcm->frame_size; - } + need_source = source->params.pcm->period_bytes; + need_sink = sink->params.pcm->period_bytes;
/* Run as many times as buffers allow */ while ((source->avail >= need_source) && (sink->free >= need_sink)) { diff --git a/src/include/reef/audio/buffer.h b/src/include/reef/audio/buffer.h index 5f2dbb7..0817a40 100644 --- a/src/include/reef/audio/buffer.h +++ b/src/include/reef/audio/buffer.h @@ -119,20 +119,20 @@ static inline void comp_update_sink_free_avail(struct comp_buffer *snk, int n) static inline void comp_wrap_source_r_ptr_circular(struct comp_buffer *src) { if (src->r_ptr >= src->end_addr) - src->r_ptr -= src->alloc_size; + src->r_ptr -= src->ipc_buffer.size;
if (src->r_ptr < src->addr) - src->r_ptr += src->alloc_size; + src->r_ptr += src->ipc_buffer.size; }
static inline void comp_wrap_sink_w_ptr_circular(struct comp_buffer *snk) { if (snk->w_ptr >= snk->end_addr) - snk->w_ptr -= snk->alloc_size; + snk->w_ptr -= snk->ipc_buffer.size;
if (snk->w_ptr < snk->addr) - snk->w_ptr += snk->alloc_size; + snk->w_ptr += snk->ipc_buffer.size; }
#endif diff --git a/src/include/uapi/ipc.h b/src/include/uapi/ipc.h index 3d78db3..d89039e 100644 --- a/src/include/uapi/ipc.h +++ b/src/include/uapi/ipc.h @@ -488,6 +488,7 @@ struct sof_ipc_comp_src { struct sof_ipc_pcm_comp pcm; uint32_t in_mask; /* SOF_RATE_ supported input rates */ uint32_t out_mask; /* SOF_RATE_ supported output rates */ + int32_t out_rate; } __attribute__((packed));
/* generic MUX component */
The default tone frequency of 997 Hz was updated to a proper Q16.16 value. Macros for tone frequency and gain were added to tone.h and a generic float to fractional value conversion macro to format.h. Also some common Q1.31 decibel constants were added. Tone function pointer set was moved to tone_new() since it is not modified later in this component.
Signed-off-by: Seppo Ingalsuo seppo.ingalsuo@linux.intel.com --- src/audio/tone.c | 29 +++++++++++++---------------- src/audio/tone.h | 7 ++++++- src/include/reef/audio/format.h | 17 ++++++++++++++++- 3 files changed, 35 insertions(+), 18 deletions(-)
diff --git a/src/audio/tone.c b/src/audio/tone.c index f45d8be..9499040 100644 --- a/src/audio/tone.c +++ b/src/audio/tone.c @@ -55,8 +55,8 @@ #define trace_tone_error(__e) trace_error(TRACE_CLASS_TONE, __e)
#define TONE_NUM_FS 13 /* Table size for 8-192 kHz range */ -#define TONE_AMPLITUDE_DEFAULT 2147484 /* -60 dB from full scale */ -#define TONE_FREQUENCY_DEFAULT 16334848 /* 997 in Q18.14 */ +#define TONE_AMPLITUDE_DEFAULT MINUS_60DB_Q1_31 /* -60 dB */ +#define TONE_FREQUENCY_DEFAULT TONE_FREQ(997.0) /* 997 Hz */
static int32_t tonegen(struct tone_state *sg); static void tonegen_control(struct tone_state *sg); @@ -80,7 +80,6 @@ struct comp_data { struct tone_state sg; void (*tone_func)(struct comp_dev *dev, struct comp_buffer *sink, struct comp_buffer *source, uint32_t frames); - };
/* @@ -129,7 +128,8 @@ static void tone_s32_default(struct comp_dev *dev, struct comp_buffer *sink, /* No need to check if past end_addr, * it is so just subtract buffer size. */ - dest = (int32_t *) ((size_t) dest - sink->alloc_size); + dest = (int32_t *) ((size_t) dest + - sink->ipc_buffer.size); } } sink->w_ptr = dest; @@ -381,7 +381,9 @@ static struct comp_dev *tone_new(struct sof_ipc_comp *comp)
comp_set_drvdata(dev, cd); comp_set_endpoint(dev); + cd->tone_func = tone_s32_default;
+ /* Reset tone generator and set channels volumes to default */ tonegen_reset(&cd->sg);
return dev; @@ -417,22 +419,19 @@ static int tone_params(struct comp_dev *dev, struct stream_params *params) static int tone_cmd(struct comp_dev *dev, int cmd, void *data) { struct comp_data *cd = comp_get_drvdata(dev); - struct sof_ipc_comp_tone *cv; + struct sof_ipc_comp_tone *ct; trace_tone("TCm");
switch (cmd) { case COMP_CMD_TONE: trace_tone("Tto"); - cv = (struct sof_ipc_comp_tone *) data; + ct = (struct sof_ipc_comp_tone *) data; /* Ignore channels while tone implementation is mono */ - tonegen_set_f(&cd->sg, cv->frequency); - tonegen_set_a(&cd->sg, cv->amplitude); - tonegen_set_sweep(&cd->sg, cv->freq_mult, cv->ampl_mult, - cv->length, cv->period, cv->repeats); - tonegen_set_linramp(&cd->sg, cv->ramp_step); - break; - case COMP_CMD_VOLUME: - trace_tone("TVo"); + tonegen_set_f(&cd->sg, ct->frequency); + tonegen_set_a(&cd->sg, ct->amplitude); + tonegen_set_sweep(&cd->sg, ct->freq_mult, ct->ampl_mult, + ct->length, ct->period, ct->repeats); + tonegen_set_linramp(&cd->sg, ct->ramp_step); break; case COMP_CMD_MUTE: trace_tone("TMu"); @@ -496,7 +495,6 @@ static int tone_copy(struct comp_dev *dev) */ need_sink = cframes * sink->params.pcm->frame_size; if (sink->free >= need_sink) { - /* create tone */ cd->tone_func(dev, sink, source, cframes); } @@ -517,7 +515,6 @@ static int tone_prepare(struct comp_dev *dev) trace_value(sink->params.pcm->channels); trace_value(sink->params.pcm->rate);
- cd->tone_func = tone_s32_default; f = tonegen_get_f(&cd->sg); a = tonegen_get_a(&cd->sg); if (tonegen_init(&cd->sg, sink->params.pcm->rate, f, a) < 0) diff --git a/src/audio/tone.h b/src/audio/tone.h index 861717c..fcaf404 100644 --- a/src/audio/tone.h +++ b/src/audio/tone.h @@ -30,6 +30,11 @@ * Keyon Jie yang.jie@linux.intel.com */
+/* Convert float frequency in Hz to Q16.16 fractional format */ +#define TONE_FREQ(f) Q_CONVERT_FLOAT(f, 16) + +/* Convert float gain to Q1.31 fractional format */ +#define TONE_GAIN(v) Q_CONVERT_FLOAT(v, 31)
struct tone_state { int mute; @@ -37,7 +42,7 @@ struct tone_state { int32_t a_target; /* Target amplitude Q1.31 */ int32_t ampl_coef; /* Amplitude multiplier Q2.30 */ int32_t c; /* Coefficient 2*pi/Fs Q1.31 */ - int32_t f; /* Frequency Q18.14 */ + int32_t f; /* Frequency Q16.16 */ int32_t freq_coef; /* Frequency multiplier Q2.30 */ int32_t fs; /* Sample rate in Hertz Q32.0 */ int32_t ramp_step; /* Amplitude ramp step Q1.31 */ diff --git a/src/include/reef/audio/format.h b/src/include/reef/audio/format.h index a1dae42..945a968 100644 --- a/src/include/reef/audio/format.h +++ b/src/include/reef/audio/format.h @@ -44,7 +44,22 @@ /* Collection of common fractional numbers */ #define ONE_Q2_30 1073741824 /* Q2.30 1.0 */ #define ONE_Q1_31 2147483647 /* Q1.31 ~1.0 */ - +#define MINUS_3DB_Q1_31 1520301996 /* 10^(-3/20) */ +#define MINUS_6DB_Q1_31 1076291389 /* 10^(-6/20) */ +#define MINUS_10DB_Q1_31 679093957 /* 10^(-10/20) */ +#define MINUS_20DB_Q1_31 214748365 /* 10^(-20/20) */ +#define MINUS_30DB_Q1_31 67909396 /* 10^(-30/20) */ +#define MINUS_40DB_Q1_31 21474836 /* 10^(-40/20) */ +#define MINUS_50DB_Q1_31 6790940 /* 10^(-50/20) */ +#define MINUS_60DB_Q1_31 2147484 /* 10^(-60/20) */ +#define MINUS_70DB_Q1_31 679094 /* 10^(-70/20) */ +#define MINUS_80DB_Q1_31 214748 /* 10^(-80/20) */ +#define MINUS_90DB_Q1_31 67909 /* 10^(-90/20) */ + +/* Convert a float number to fractional Qnx.ny format. Note that there is no + * check for nx+ny number of bits to fit the word length of int. + */ +#define Q_CONVERT_FLOAT(f, qy) ((int)((f) * (1 << qy) + 0.5)) /* f is float */
/* A more clever macro for Q-shifts */ #define Q_SHIFT(x, src_q, dst_q) ((x)>>((src_q)-(dst_q)))
A free of null pointer is fixed with this change. Also the possibility of nondefined number of channels in EQ config or switch command is eliminated by by initializing the FIR for max channels. An error of -ENOMEM is propagated in functions and returned if allocation in config or switch response fails.
Signed-off-by: Seppo Ingalsuo seppo.ingalsuo@linux.intel.com --- src/audio/eq_fir.c | 48 +++++++++++++++++++++++++++++++----------------- src/audio/eq_fir.h | 2 +- src/include/uapi/ipc.h | 6 ++++++ 3 files changed, 38 insertions(+), 18 deletions(-)
diff --git a/src/audio/eq_fir.c b/src/audio/eq_fir.c index 5617313..f936a47 100644 --- a/src/audio/eq_fir.c +++ b/src/audio/eq_fir.c @@ -175,6 +175,9 @@ static int eq_fir_setup(struct fir_state_32x16 fir[], } }
+ /* Free existing FIR channels data if it was allocated */ + eq_fir_free_delaylines(fir); + /* Initialize 1st phase */ for (i = 0; i < nch; i++) { resp = config->assign_response[i]; @@ -191,14 +194,12 @@ static int eq_fir_setup(struct fir_state_32x16 fir[], }
} - /* Free existing FIR channels data if it was allocated */ - eq_fir_free_delaylines(fir);
/* Allocate all FIR channels data in a big chunk and clear it */ fir_data = rballoc(RZONE_SYS, RFLAGS_NONE, length_sum * sizeof(int32_t)); if (fir_data == NULL) - return -EINVAL; + return -ENOMEM;
memset(fir_data, 0, length_sum * sizeof(int32_t));
@@ -220,7 +221,7 @@ static int eq_fir_switch_response(struct fir_state_32x16 fir[], struct eq_fir_configuration *config, struct eq_fir_update *update, int nch) { - int i; + int i, ret;
/* Copy assign response from update and re-initilize EQ */ if (config == NULL) @@ -231,9 +232,9 @@ static int eq_fir_switch_response(struct fir_state_32x16 fir[], config->assign_response[i] = update->assign_response[i]; }
- eq_fir_setup(fir, config, nch); + ret = eq_fir_setup(fir, config, nch);
- return 0; + return ret; }
/* @@ -306,21 +307,26 @@ static int eq_fir_cmd(struct comp_dev *dev, int cmd, void *data) { trace_src("ECm"); struct comp_data *cd = comp_get_drvdata(dev); - struct comp_buffer *source = list_first_item(&dev->bsource_list, - struct comp_buffer, sink_list); struct sof_ipc_eq_fir_blob *blob; struct sof_ipc_eq_fir_switch *assign; - + struct eq_fir_update *fir_update; int i; + int ret = 0; size_t bs;
switch (cmd) { case COMP_CMD_EQ_FIR_SWITCH: trace_src("EFx"); assign = (struct sof_ipc_eq_fir_switch *) data; - eq_fir_switch_response(cd->fir, cd->config, - (struct eq_fir_update *) assign->data, - source->params.pcm->channels); + fir_update = (struct eq_fir_update *) assign->data; + ret = eq_fir_switch_response(cd->fir, cd->config, + fir_update, PLATFORM_MAX_CHANNELS); + + /* Print trace information */ + tracev_value(iir_update->stream_max_channels); + for (i = 0; i < fir_update->stream_max_channels; i++) + tracev_value(iir_update->assign_response[i]); + break; case COMP_CMD_EQ_FIR_CONFIG: trace_src("EFc"); @@ -338,7 +344,14 @@ static int eq_fir_cmd(struct comp_dev *dev, int cmd, void *data) return -EINVAL;
memcpy(cd->config, blob->data, bs); - eq_fir_setup(cd->fir, cd->config, source->params.pcm->channels); + ret = eq_fir_setup(cd->fir, cd->config, PLATFORM_MAX_CHANNELS); + + /* Print trace information */ + tracev_value(cd->config->stream_max_channels); + tracev_value(cd->config->number_of_responses_defined); + for (i = 0; i < cd->config->stream_max_channels; i++) + tracev_value(cd->config->assign_response[i]); + break; case COMP_CMD_MUTE: trace_src("EFm"); @@ -378,10 +391,9 @@ static int eq_fir_cmd(struct comp_dev *dev, int cmd, void *data) break; default: trace_src("EDf"); - break; }
- return 0; + return ret; }
/* copy and process stream data from source to sink buffers */ @@ -419,6 +431,7 @@ static int eq_fir_prepare(struct comp_dev *dev) { struct comp_data *cd = comp_get_drvdata(dev); struct comp_buffer *source; + int ret;
trace_src("EPp");
@@ -430,8 +443,9 @@ static int eq_fir_prepare(struct comp_dev *dev)
source = list_first_item(&dev->bsource_list, struct comp_buffer, sink_list); - if (eq_fir_setup(cd->fir, cd->config, source->params.pcm->channels) < 0) - return -EINVAL; + ret = eq_fir_setup(cd->fir, cd->config, source->params.pcm->channels); + if (ret < 0) + return ret;
//dev->preload = PLAT_INT_PERIODS; dev->state = COMP_STATE_PREPARE; diff --git a/src/audio/eq_fir.h b/src/audio/eq_fir.h index 0b5dbb1..7579ba4 100644 --- a/src/audio/eq_fir.h +++ b/src/audio/eq_fir.h @@ -52,7 +52,7 @@
#define NHEADER_EQ_FIR_BLOB 2 /* Header is two words plus assigns plus coef */
-#define EQ_FIR_MAX_BLOB_SIZE 4096 /* Max size allowed for blob */ +#define EQ_FIR_MAX_BLOB_SIZE 4096 /* Max size allowed for blob in bytes */
struct eq_fir_configuration { uint16_t stream_max_channels; diff --git a/src/include/uapi/ipc.h b/src/include/uapi/ipc.h index d89039e..db7a8bb 100644 --- a/src/include/uapi/ipc.h +++ b/src/include/uapi/ipc.h @@ -511,6 +511,12 @@ struct sof_ipc_comp_tone { int32_t ramp_step; } __attribute__((packed));
+/* FIR equalizer component */ +struct sof_ipc_comp_eq_fir { + struct sof_ipc_comp comp; + struct sof_ipc_pcm_comp pcm; +} __attribute__((packed)); + /* IPC to pass configuration blobs to equalizers and re-assign responses */ struct sof_ipc_eq_fir_blob { struct sof_ipc_comp comp;
Initialize EQ for max number of channels in configuration or switch commands to avoid not set number of channels. A return value of -ENOMEM is propagated in init functions and returned if allocation for memory fails.
Some trace output is added into EQ setup and some comments cleaned and added.
Signed-off-by: Seppo Ingalsuo seppo.ingalsuo@linux.intel.com --- src/audio/eq_iir.c | 55 +++++++++++++++++++++++++++++++++----------------- src/audio/eq_iir.h | 2 +- src/include/uapi/ipc.h | 6 ++++++ 3 files changed, 44 insertions(+), 19 deletions(-)
diff --git a/src/audio/eq_iir.c b/src/audio/eq_iir.c index 8d12895..0f43198 100644 --- a/src/audio/eq_iir.c +++ b/src/audio/eq_iir.c @@ -205,7 +205,7 @@ static int eq_iir_setup(struct iir_state_df2t iir[], /* Allocate all IIR channels data in a big chunk and clear it */ iir_delay = rmalloc(RZONE_RUNTIME, RFLAGS_NONE, size_sum); if (iir_delay == NULL) - return -EINVAL; + return -ENOMEM;
memset(iir_delay, 0, size_sum);
@@ -226,7 +226,7 @@ static int eq_iir_switch_response(struct iir_state_df2t iir[], struct eq_iir_configuration *config, struct eq_iir_update *update, int nch) { - int i; + int i, ret;
/* Copy assign response from update and re-initilize EQ */ if (config == NULL) @@ -237,9 +237,9 @@ static int eq_iir_switch_response(struct iir_state_df2t iir[], config->assign_response[i] = update->assign_response[i]; }
- eq_iir_setup(iir, config, nch); + ret = eq_iir_setup(iir, config, nch);
- return 0; + return ret; }
/* @@ -312,19 +312,26 @@ static int eq_iir_cmd(struct comp_dev *dev, int cmd, void *data) { trace_eq_iir("ECm"); struct comp_data *cd = comp_get_drvdata(dev); - struct comp_buffer *source = list_first_item(&dev->bsource_list, - struct comp_buffer, sink_list); struct sof_ipc_eq_iir_switch *assign; struct sof_ipc_eq_iir_blob *blob; + struct eq_iir_update *iir_update; int i; + int ret = 0; size_t bs; + switch (cmd) { case COMP_CMD_EQ_IIR_SWITCH: trace_eq_iir("EFx"); assign = (struct sof_ipc_eq_iir_switch *) data; - eq_iir_switch_response(cd->iir, cd->config, - (struct eq_iir_update *) assign->data, - source->params.pcm->channels); + iir_update = (struct eq_iir_update *) assign->data; + ret = eq_iir_switch_response(cd->iir, cd->config, + iir_update, PLATFORM_MAX_CHANNELS); + + /* Print trace information */ + tracev_value(iir_update->stream_max_channels); + for (i = 0; i < iir_update->stream_max_channels; i++) + tracev_value(iir_update->assign_response[i]); + break; case COMP_CMD_EQ_IIR_CONFIG: trace_eq_iir("EFc"); @@ -333,7 +340,8 @@ static int eq_iir_cmd(struct comp_dev *dev, int cmd, void *data)
/* Copy new config, need to decode data to know the size */ blob = (struct sof_ipc_eq_iir_blob *) data; - bs = blob->comp.hdr.size - sizeof(struct sof_ipc_hdr); + bs = blob->comp.hdr.size - sizeof(struct sof_ipc_hdr) + - sizeof(struct sof_ipc_host_buffer); if (bs > EQ_IIR_MAX_BLOB_SIZE) return -EINVAL;
@@ -343,7 +351,16 @@ static int eq_iir_cmd(struct comp_dev *dev, int cmd, void *data) return -EINVAL;
memcpy(cd->config, blob->data, bs); - eq_iir_setup(cd->iir, cd->config, source->params.pcm->channels); + /* Initialize all channels, the actual number of channels may + * not be set yet. */ + ret = eq_iir_setup(cd->iir, cd->config, PLATFORM_MAX_CHANNELS); + + /* Print trace information */ + tracev_value(cd->config->stream_max_channels); + tracev_value(cd->config->number_of_responses_defined); + for (i = 0; i < cd->config->stream_max_channels; i++) + tracev_value(cd->config->assign_response[i]); + break; case COMP_CMD_MUTE: trace_eq_iir("EFm"); @@ -386,7 +403,7 @@ static int eq_iir_cmd(struct comp_dev *dev, int cmd, void *data) break; }
- return 0; + return ret; }
/* copy and process stream data from source to sink buffers */ @@ -409,9 +426,6 @@ static int eq_iir_copy(struct comp_dev *dev) /* Check that source has enough frames available and that sink has * enough frames free. */ - //frames = source->params.period_frames; - //need_source = frames * source->params.frame_size; - //need_sink = frames * sink->params.frame_size; frames = source->params.pcm->period_count; need_source = frames * source->params.pcm->frame_size; need_sink = frames * sink->params.pcm->frame_size; @@ -427,19 +441,24 @@ static int eq_iir_prepare(struct comp_dev *dev) { struct comp_data *cd = comp_get_drvdata(dev); struct comp_buffer *source; + int ret;
trace_eq_iir("EPp");
cd->eq_iir_func = eq_iir_s32_default;
- /* Initialize EQ */ + /* Initialize EQ. Note that if EQ has not received command to + * configure the response the EQ prepare returns an error that + * interrupts pipeline prepare for downstream. + */ if (cd->config == NULL) return -EINVAL;
source = list_first_item(&dev->bsource_list, struct comp_buffer, sink_list); - if (eq_iir_setup(cd->iir, cd->config, source->params.pcm->channels) < 0) - return -EINVAL; + ret = eq_iir_setup(cd->iir, cd->config, source->params.pcm->channels); + if (ret < 0) + return ret;
//dev->preload = PLAT_INT_PERIODS; dev->state = COMP_STATE_PREPARE; diff --git a/src/audio/eq_iir.h b/src/audio/eq_iir.h index 2634986..42d95c1 100644 --- a/src/audio/eq_iir.h +++ b/src/audio/eq_iir.h @@ -64,7 +64,7 @@ * {0, 0, 0, 0, 1073741824, 0, 16484} */
-#define EQ_IIR_MAX_BLOB_SIZE 1024 +#define EQ_IIR_MAX_BLOB_SIZE 1024 /* In bytes or size_t */
#define NHEADER_EQ_IIR_BLOB 2 /* Blob is two words plus asssigns plus coef */
diff --git a/src/include/uapi/ipc.h b/src/include/uapi/ipc.h index db7a8bb..ea9d1c6 100644 --- a/src/include/uapi/ipc.h +++ b/src/include/uapi/ipc.h @@ -517,6 +517,12 @@ struct sof_ipc_comp_eq_fir { struct sof_ipc_pcm_comp pcm; } __attribute__((packed));
+/* IIR equalizer component */ +struct sof_ipc_comp_eq_iir { + struct sof_ipc_comp comp; + struct sof_ipc_pcm_comp pcm; +} __attribute__((packed)); + /* IPC to pass configuration blobs to equalizers and re-assign responses */ struct sof_ipc_eq_fir_blob { struct sof_ipc_comp comp;
On Wed, 2017-06-28 at 13:32 +0300, Seppo Ingalsuo wrote:
SRC updates sink and downstream pipeline PCM rate, period_count and period_bytes in src_params() according to received out_rate via IPC. Also the use of incorrect alloc_size is replaced by ipc_buffer.size.
Signed-off-by: Seppo Ingalsuo seppo.ingalsuo@linux.intel.com
src/audio/src.c | 90 ++++++++++++++++++++++++----------------- src/include/reef/audio/buffer.h | 8 ++-- src/include/uapi/ipc.h | 1 + 3 files changed, 57 insertions(+), 42 deletions(-)
diff --git a/src/audio/src.c b/src/audio/src.c index c338220..f1f4b86 100644 --- a/src/audio/src.c +++ b/src/audio/src.c @@ -56,9 +56,13 @@ /* src component private data */ struct comp_data { struct polyphase_src src[PLATFORM_MAX_CHANNELS];
- /* Next two elements must be kept in this order since
* the end of pcm_params is a flexible array.
*/
- struct sof_ipc_pcm_params pcm_params;
- enum sof_ipc_chmap channel_map[PLATFORM_MAX_CHANNELS]; int32_t *delay_lines; int scratch_length;
- //int32_t z[STAGE_BUF_SIZE]; void (*src_func)(struct comp_dev *dev, struct comp_buffer *source, struct comp_buffer *sink,
@@ -155,7 +159,7 @@ static void src_2s_s32_default(struct comp_dev *dev,
s1.times = n_times1; s1.x_end_addr = source->end_addr;
- s1.x_size = source->alloc_size;
- s1.x_size = source->ipc_buffer.size;
buffer size is correct, the alloc size is the size actually returned by the allocator an may be larger than the requested buffer size (since the allocator only allocates on discrete sizes).
s1.x_inc = nch; s1.y_end_addr = &cd->delay_lines[cd->scratch_length]; s1.y_size = STAGE_BUF_SIZE * sizeof(int32_t); @@ -166,7 +170,7 @@ static void src_2s_s32_default(struct comp_dev *dev, s2.x_size = STAGE_BUF_SIZE * sizeof(int32_t); s2.x_inc = 1; s2.y_end_addr = sink->end_addr;
- s2.y_size = sink->alloc_size;
s2.y_size = sink->ipc_buffer.size; s2.y_inc = nch;
s1.x_rptr = src + nch - 1;
@@ -227,10 +231,10 @@ static void src_1s_s32_default(struct comp_dev *dev,
s1.times = n_times; s1.x_end_addr = source->end_addr;
- s1.x_size = source->alloc_size;
- s1.x_size = source->ipc_buffer.size; s1.x_inc = nch; s1.y_end_addr = sink->end_addr;
- s1.y_size = sink->alloc_size;
- s1.y_size = sink->ipc_buffer.size; s1.y_inc = nch; s1.x_rptr = src + nch - 1; s1.y_wptr = dest + nch - 1;
@@ -263,7 +267,7 @@ static struct comp_dev *src_new(struct sof_ipc_comp *comp) { struct comp_dev *dev; struct sof_ipc_comp_src *src;
- struct sof_ipc_comp_src *ipc_src = (struct sof_ipc_comp_src *)comp;
- struct sof_ipc_comp_src *ipc_src = (struct sof_ipc_comp_src *) comp; struct comp_data *cd; int i;
@@ -274,7 +278,7 @@ static struct comp_dev *src_new(struct sof_ipc_comp *comp) if (dev == NULL) return NULL;
- src = (struct sof_ipc_comp_src *)&dev->comp;
src = (struct sof_ipc_comp_src *) &dev->comp; memcpy(src, ipc_src, sizeof(struct sof_ipc_comp_src));
cd = rmalloc(RZONE_RUNTIME, RFLAGS_NONE, sizeof(*cd));
@@ -317,6 +321,7 @@ static int src_params(struct comp_dev *dev, struct stream_params *params) int32_t *buffer_start; int n = 0; struct comp_data *cd = comp_get_drvdata(dev);
struct sof_ipc_comp_src *src = (struct sof_ipc_comp_src *) &dev->comp;
trace_src("SPa");
@@ -325,23 +330,43 @@ static int src_params(struct comp_dev *dev, struct stream_params *params) || (params->pcm->frame_fmt != SOF_IPC_FRAME_S32_LE)) return -EINVAL;
- /* No data transformation */
- comp_set_sink_params(dev, params);
- /* Allocate needed memory for delay lines */ source = list_first_item(&dev->bsource_list, struct comp_buffer, sink_list); sink = list_first_item(&dev->bsink_list, struct comp_buffer, source_list);
- src_buffer_lengths(&need, source->params.pcm->rate,
sink->params.pcm->rate, source->params.pcm->channels);
/* Copy PCM stream parameters and the channel map array */
memcpy(&cd->pcm_params, &(*params->pcm),
sizeof(struct sof_ipc_pcm_params));
for (i = 0; i < params->pcm->channels; i++)
cd->pcm_params.channel_map[i] = params->pcm->channel_map[i];
/* Point sink stream parameters to copy */
sink->params.pcm = &cd->pcm_params;
/* Stored IPC from src_new() contains the output rate for sink,
* set the new rate for sink.
*/
sink->params.pcm->rate = src->out_rate;
/* Adjust sink buffer parameters to match fs_out/fs_in */
sink->params.pcm->period_count = sink->params.pcm->period_count
* sink->params.pcm->rate / source->params.pcm->rate;
sink->params.pcm->period_bytes = sink->params.pcm->period_bytes
* sink->params.pcm->rate / source->params.pcm->rate;
/* Allocate needed memory for delay lines */
if (src_buffer_lengths(&need, source->params.pcm->rate,
sink->params.pcm->rate, source->params.pcm->channels) < 0)
return -EINVAL;
delay_lines_size = sizeof(int32_t) * need.total; if (cd->delay_lines != NULL) rfree(cd->delay_lines);
cd->delay_lines = rmalloc(RZONE_RUNTIME, RFLAGS_NONE, delay_lines_size); if (cd->delay_lines == NULL)
return -EINVAL;
return -ENOMEM;
/* Clear all delay lines here */ memset(cd->delay_lines, 0, delay_lines_size);
@@ -369,19 +394,20 @@ static int src_params(struct comp_dev *dev, struct stream_params *params) */ trace_src("SFa"); cd->src_func = fallback_s32;
return(-EINVAL);
break;
rfree(cd->delay_lines);
return -EINVAL;
}
/* Check that src blk_in and blk_out are less than params.period_frames.
- Return an error if the period is too short.
*/
- if (src_polyphase_get_blk_in(&cd->src[0]) > source->params.pcm->period_count)
return(-EINVAL);
- if (src_polyphase_get_blk_out(&cd->src[0]) > sink->params.pcm->period_count)
return(-EINVAL);
if (src_polyphase_get_blk_in(&cd->src[0])
> source->params.pcm->period_count)
return -EINVAL;
if (src_polyphase_get_blk_out(&cd->src[0])
> sink->params.pcm->period_count)
return -EINVAL;
return 0;
} @@ -453,7 +479,8 @@ static int src_copy(struct comp_dev *dev) struct comp_buffer *sink; uint32_t frames_source; uint32_t frames_sink;
- int need_source, need_sink, min_frames;
int need_source, need_sink;
// int min_frames;
trace_comp("SRC");
@@ -464,25 +491,12 @@ static int src_copy(struct comp_dev *dev) source_list);
/* Check that source has enough frames available and sink enough
* frames free.
*/ frames_source = source->params.pcm->period_count; frames_sink = sink->params.pcm->period_count;* frames free. Increase tried period_count if not sufficient to run.
- min_frames = src_polyphase_get_blk_in(&cd->src[0]);
- if (frames_source > min_frames)
need_source = frames_source * source->params.pcm->frame_size;
- else {
frames_source = min_frames;
need_source = min_frames * source->params.pcm->frame_size;
- }
- min_frames = src_polyphase_get_blk_out(&cd->src[0]);
- if (frames_sink > min_frames)
need_sink = frames_sink * sink->params.pcm->frame_size;
- else {
frames_sink = min_frames;
need_sink = min_frames * sink->params.pcm->frame_size;
- }
need_source = source->params.pcm->period_bytes;
need_sink = sink->params.pcm->period_bytes;
/* Run as many times as buffers allow */ while ((source->avail >= need_source) && (sink->free >= need_sink)) {
diff --git a/src/include/reef/audio/buffer.h b/src/include/reef/audio/buffer.h index 5f2dbb7..0817a40 100644 --- a/src/include/reef/audio/buffer.h +++ b/src/include/reef/audio/buffer.h @@ -119,20 +119,20 @@ static inline void comp_update_sink_free_avail(struct comp_buffer *snk, int n) static inline void comp_wrap_source_r_ptr_circular(struct comp_buffer *src) { if (src->r_ptr >= src->end_addr)
src->r_ptr -= src->alloc_size;
src->r_ptr -= src->ipc_buffer.size; if (src->r_ptr < src->addr)
src->r_ptr += src->alloc_size;
src->r_ptr += src->ipc_buffer.size;
}
static inline void comp_wrap_sink_w_ptr_circular(struct comp_buffer *snk) { if (snk->w_ptr >= snk->end_addr)
snk->w_ptr -= snk->alloc_size;
snk->w_ptr -= snk->ipc_buffer.size; if (snk->w_ptr < snk->addr)
snk->w_ptr += snk->alloc_size;
snk->w_ptr += snk->ipc_buffer.size;
}
#endif diff --git a/src/include/uapi/ipc.h b/src/include/uapi/ipc.h index 3d78db3..d89039e 100644 --- a/src/include/uapi/ipc.h +++ b/src/include/uapi/ipc.h @@ -488,6 +488,7 @@ struct sof_ipc_comp_src { struct sof_ipc_pcm_comp pcm; uint32_t in_mask; /* SOF_RATE_ supported input rates */ uint32_t out_mask; /* SOF_RATE_ supported output rates */
- int32_t out_rate;
} __attribute__((packed));
/* generic MUX component */
--------------------------------------------------------------------- Intel Corporation (UK) Limited Registered No. 1134945 (England) Registered Office: Pipers Way, Swindon SN3 1RJ VAT No: 860 2173 47
This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). Any review or distribution by others is strictly prohibited. If you are not the intended recipient, please contact the sender and delete all copies.
participants (2)
-
Liam Girdwood
-
Seppo Ingalsuo