diff --git a/src/audio/src/src.c b/src/audio/src/src.c index 6efad8fcdf47..741106e5923e 100644 --- a/src/audio/src/src.c +++ b/src/audio/src/src.c @@ -128,8 +128,8 @@ int src_buffer_lengths(struct src_param *a, int fs_in, int fs_out, int nch, /* Check from stage1 parameter for a deleted in/out rate combination.*/ if (stage1->filter_length < 1) { trace_src_error("src_buffer_lengths() error: " - "stage1->filter_length <" - " 1, fs_in: %u, fs_out: %u", fs_in, fs_out); + "Non-supported combination " + "fs_in = %d, fs_out = %d", fs_in, fs_out); return -EINVAL; } @@ -603,9 +603,6 @@ static int src_params(struct comp_dev *dev) return err; } - trace_src("src_params(), blk_in = %u, blk_out = %u", - cd->param.blk_in, cd->param.blk_out); - delay_lines_size = sizeof(int32_t) * cd->param.total; if (delay_lines_size == 0) { trace_src_error("src_params() error: delay_lines_size = 0"); @@ -803,31 +800,6 @@ static int src_prepare(struct comp_dev *dev) if (ret == COMP_STATUS_STATE_ALREADY_SET) return PPL_STATUS_PATH_STOP; - /* SRC supports S16_LE, S24_4LE and S32_LE formats */ - switch (dev->params.frame_fmt) { - case SOF_IPC_FRAME_S16_LE: - cd->data_shift = 0; - cd->polyphase_func = src_polyphase_stage_cir_s16; - /* Copy function is set by default in params() for 32 bit - * data. Change it to 16 bit version here if source and sink - * rates are equal. - */ - if (cd->source_rate == cd->sink_rate) - cd->src_func = src_copy_s16; - break; - case SOF_IPC_FRAME_S24_4LE: - cd->data_shift = 8; - cd->polyphase_func = src_polyphase_stage_cir; - break; - case SOF_IPC_FRAME_S32_LE: - cd->data_shift = 0; - cd->polyphase_func = src_polyphase_stage_cir; - break; - default: - trace_src_error("src_prepare() error: invalid dev->frame_fmt"); - return -EINVAL; - } - /* SRC component will only ever have 1 source and 1 sink buffer */ sourceb = list_first_item(&dev->bsource_list, struct comp_buffer, sink_list); @@ -871,6 +843,41 @@ static int src_prepare(struct comp_dev *dev) goto err; } + /* SRC supports S16_LE, S24_4LE and S32_LE formats */ + if (cd->source_format != cd->sink_format) { + trace_src_error("src_prepare() error: " + "Source fmt %d and sink fmt %d are different.", + cd->source_format, cd->sink_format); + ret = -EINVAL; + goto err; + } + + switch (cd->source_format) { + case SOF_IPC_FRAME_S16_LE: + cd->data_shift = 0; + cd->polyphase_func = src_polyphase_stage_cir_s16; + /* Copy function is set by default in params() for 32 bit + * data. Change it to 16 bit version here if source and sink + * rates are equal. + */ + if (cd->source_rate == cd->sink_rate) + cd->src_func = src_copy_s16; + break; + case SOF_IPC_FRAME_S24_4LE: + cd->data_shift = 8; + cd->polyphase_func = src_polyphase_stage_cir; + break; + case SOF_IPC_FRAME_S32_LE: + cd->data_shift = 0; + cd->polyphase_func = src_polyphase_stage_cir; + break; + default: + trace_src_error("src_prepare() error: invalid format %d", + cd->source_format); + ret = -EINVAL; + goto err; + } + return 0; err: diff --git a/tools/topology/CMakeLists.txt b/tools/topology/CMakeLists.txt index bb8dbe95667f..6f4ea54e1015 100644 --- a/tools/topology/CMakeLists.txt +++ b/tools/topology/CMakeLists.txt @@ -52,6 +52,7 @@ set(TPLGS "sof-icl-nocodec\;sof-icl-nocodec" "sof-apl-eq-pcm512x\;sof-apl-eq-pcm512x" "sof-apl-eq-dmic\;sof-apl-eq-dmic" + "sof-apl-src-dmic\;sof-apl-src-dmic" "sof-apl-dmic-a2ch\;sof-apl-dmic-a2ch" "sof-apl-dmic-b2ch\;sof-apl-dmic-b2ch" "sof-apl-dmic-a2ch-b2ch\;sof-apl-dmic-a2ch-b2ch" diff --git a/tools/topology/sof-apl-src-dmic.m4 b/tools/topology/sof-apl-src-dmic.m4 new file mode 100644 index 000000000000..de6cd1c7552b --- /dev/null +++ b/tools/topology/sof-apl-src-dmic.m4 @@ -0,0 +1,104 @@ +# +# Topology for Apollo Lake with direct attach digital microphones array +# + +# Capture configuration +# DAI0 2ch 32b mic1-2 +# DAI1 2ch 32b mic1-2 + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') + +# Include TLV library +include(`common/tlv.m4') + +# Include Token library +include(`sof/tokens.m4') + +# Include Apollolake DSP configuration +include(`platform/intel/bxt.m4') +include(`platform/intel/dmic.m4') + +DEBUG_START + +# +# Define the pipelines +# +# PCM6 <--- Volume <--- SRC <--- DMIC6 (DMIC01) +# PCM7 <--- Volume <--- SRC <--- DMIC7 (DMIC16k) +# + +dnl PIPELINE_PCM_DAI_ADD(pipeline, +dnl pipe id, pcm, max channels, format, +dnl period, priority, core, +dnl dai type, dai_index, dai format, +dnl dai periods, pcm_min_rate, pcm_max_rate, +dnl pipeline_rate, time_domain) + +# SRC capture pipeline 6 on PCM 6 using max channels 2. +# Set 1000us deadline on core 0 with priority 0 +PIPELINE_PCM_DAI_ADD(sof/pipe-src-volume-capture.m4, + 6, 6, 2, s32le, + 1000, 0, 0, DMIC, 0, s32le, 3, + 8000, 48000, 48000) + +# SRC capture pipeline 7 on PCM 7 using max channels 2. +# Set 1000us deadline on core 0 with priority 0 +PIPELINE_PCM_DAI_ADD(sof/pipe-src-volume-capture.m4, + 7, 7, 2, s32le, + 1000, 0, 0, DMIC, 1, s32le, 3, + 8000, 48000, 16000) + +# +# DAIs configuration +# + +dnl DAI_ADD(pipeline, +dnl pipe id, dai type, dai_index, dai_be, +dnl buffer, periods, format, +dnl deadline, priority, core, time_domain) + +# capture DAI is DMIC 0 using 3 periods +# Buffers use s32le format, 1000us deadline on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-capture.m4, + 6, DMIC, 0, NoCodec-6, + PIPELINE_SINK_6, 3, s32le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# capture DAI is DMIC 1 using 3 periods +# Buffers use s32le format, 1000us deadline on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-capture.m4, + 7, DMIC, 1, NoCodec-7, + PIPELINE_SINK_7, 3, s32le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) +dnl PCM_CAPTURE_ADD(name, pipeline, capture) +PCM_CAPTURE_ADD(DMIC01, 6, PIPELINE_PCM_6) +PCM_CAPTURE_ADD(DMIC16k, 7, PIPELINE_PCM_7) + +# +# BE configurations - overrides config in ACPI if present +# + +dnl DAI_CONFIG(type, dai_index, link_id, name, ssp_config/dmic_config) + +DAI_CONFIG(DMIC, 0, 6, NoCodec-6, + dnl DMIC_CONFIG(driver_version, clk_min, clk_mac, duty_min, duty_max, + dnl sample_rate, fifo word length, unmute time, type, + dnl dai_index, pdm controller config) + DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, + DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, + PDM_CONFIG(DMIC, 0, STEREO_PDM0))) + +DAI_CONFIG(DMIC, 1, 7, NoCodec-7, + dnl DMIC_CONFIG(driver_version, clk_min, clk_mac, duty_min, duty_max, + dnl sample_rate, fifo word length, unmute time, type, + dnl dai_index, pdm controller config) + DMIC_CONFIG(1, 500000, 4800000, 40, 60, 16000, + DMIC_WORD_LENGTH(s32le), 400, DMIC, 1, + PDM_CONFIG(DMIC, 1, STEREO_PDM0))) + +DEBUG_END diff --git a/tools/topology/sof/pipe-src-capture.m4 b/tools/topology/sof/pipe-src-capture.m4 index 4878da4a73c3..9700f40104ff 100644 --- a/tools/topology/sof/pipe-src-capture.m4 +++ b/tools/topology/sof/pipe-src-capture.m4 @@ -1,48 +1,58 @@ -# Low Latency Passthrough with volume Pipeline and PCM +# Capture pipeline with SRC and PCM # # Pipeline Endpoints for connection are :- # -# host PCM_P --> SRC --> sink DAI0 +# host PCM_C <-- B0 <-- SRC <-- B1 <-- sink DAI0 # Include topology builder +include(`pipeline.m4') +include(`buffer.m4') include(`utils.m4') include(`src.m4') -include(`buffer.m4') include(`pcm.m4') include(`dai.m4') -include(`pipeline.m4') + +# +# Controls +# # # Components and Buffers # # Host "Passthrough Capture" PCM -# with 4 sink and 0 source periods -W_PCM_CAPTURE(PCM_ID, Passthrough Capture, 4, 0) +# with 0 sink and 3 source periods +W_PCM_CAPTURE(PCM_ID, SRC Capture, 0, 3) # # SRC Configuration # -W_VENDORTUPLES(media_src_tokens, sof_src_tokens, LIST(` ', `SOF_TKN_SRC_RATE_IN "PIPELINE_RATE"')) +# Create unique names for data to allow several different input rate instances +define(MY_SRC_TOKENS, concat(`src_tokens_', PIPELINE_ID)) +define(MY_SRC_CONF, concat(`src_conf_', PIPELINE_ID)) +W_VENDORTUPLES(MY_SRC_TOKENS, sof_src_tokens, + LIST(` ', `SOF_TKN_SRC_RATE_IN "PIPELINE_RATE"')) -W_DATA(media_src_conf, media_src_tokens) +W_DATA(MY_SRC_CONF, MY_SRC_TOKENS) -# "SRC" has 4 source and 4 sink periods -W_SRC(0, PIPELINE_FORMAT, 4, 4, media_src_conf) +# "SRC" has x source and 3 sink periods +W_SRC(0, PIPELINE_FORMAT, DAI_PERIODS, 3, MY_SRC_CONF) # Capture Buffers -W_BUFFER(0, COMP_BUFFER_SIZE(4, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), +W_BUFFER(0, COMP_BUFFER_SIZE(3, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), + PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_HOST_MEM_CAP) -W_BUFFER(1, COMP_BUFFER_SIZE(4, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_DAI_MEM_CAP) # # Pipeline Graph # -# host PCM_P <-- B0 <-- SRC 0 <-- B1 <-- sink DAI0 +# host PCM_C <-- B0 <-- SRC <-- B1 <-- sink DAI0 P_GRAPH(pipe-pass-src-capture-PIPELINE_ID, PIPELINE_ID, LIST(` ', @@ -54,10 +64,16 @@ P_GRAPH(pipe-pass-src-capture-PIPELINE_ID, PIPELINE_ID, # Pipeline Source and Sinks # indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(1)) -indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Capture PCM_ID) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), + SRC Capture PCM_ID) # # PCM Configuration # -PCM_CAPABILITIES(Passthrough Capture PCM_ID, `S32_LE,S24_LE,S16_LE', PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) +PCM_CAPABILITIES(SRC Capture PCM_ID, `S32_LE,S24_LE,S16_LE', + PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +undefine(`MY_SRC_TOKENS') +undefine(`MY_SRC_CONF') diff --git a/tools/topology/sof/pipe-src-volume-capture.m4 b/tools/topology/sof/pipe-src-volume-capture.m4 new file mode 100644 index 000000000000..9be2d22d6aec --- /dev/null +++ b/tools/topology/sof/pipe-src-volume-capture.m4 @@ -0,0 +1,114 @@ +# Capture pipeline with volume, SRC, and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <-- SRC <-- B1 <-- PGA <-- B2 <-- sink DAI0 + +# Include topology builder +include(`mixercontrol.m4') +include(`pipeline.m4') +include(`buffer.m4') +include(`utils.m4') +include(`src.m4') +include(`pcm.m4') +include(`dai.m4') +include(`pga.m4') + +# +# Controls +# + +# Volume Mixer control with max value of 32 +C_CONTROLMIXER(Master Capture Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, + 256 binds the mixer control to volume get/put handlers, + 256, 256), + CONTROLMIXER_MAX(, 80), + false, + CONTROLMIXER_TLV(TLV 80 steps from -50dB to +30dB for 1dB, vtlv_m50s1), + Channel register and shift for Front Left/Right, + LIST(` ', KCONTROL_CHANNEL(FL, 1, 0), KCONTROL_CHANNEL(FR, 1, 1))) + +# Volume Configuration +define(MY_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(MY_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) +W_VENDORTUPLES(MY_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) + +W_DATA(MY_PGA_CONF, MY_PGA_TOKENS) + +# +# Components and Buffers +# + +# Host "Passthrough Capture" PCM +# with 0 sink and 3 source periods +W_PCM_CAPTURE(PCM_ID, SRC Capture, 0, 3) + +# +# SRC Configuration +# + +# Create unique names for data to allow several different input rate instances +define(MY_SRC_TOKENS, concat(`src_tokens_', PIPELINE_ID)) +define(MY_SRC_CONF, concat(`src_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(MY_SRC_TOKENS, sof_src_tokens, + LIST(` ', `SOF_TKN_SRC_RATE_IN "PIPELINE_RATE"')) + +W_DATA(MY_SRC_CONF, MY_SRC_TOKENS) + +# "SRC" has 3 source and 3 sink periods +W_SRC(0, PIPELINE_FORMAT, 3, 3, MY_SRC_CONF) + +# "Volume" has x source and 3 sink periods +W_PGA(0, PIPELINE_FORMAT, DAI_PERIODS, 3, MY_PGA_CONF, + LIST(` ', "PIPELINE_ID Master Capture Volume")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(3, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), + PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(3, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), + PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_C <-- B0 <-- SRC <-- B1 <-- PGA <-- B2 <-- sink DAI0 + +P_GRAPH(pipe-pass-src-capture-PIPELINE_ID, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), N_SRC(0))', + `dapm(N_SRC(0), N_BUFFER(1))', + `dapm(N_BUFFER(1), N_PGA(0))', + `dapm(N_PGA(0), N_BUFFER(2))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), + SRC Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(SRC Capture PCM_ID, `S32_LE,S24_LE,S16_LE', + PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +undefine(`MY_PGA_TOKENS') +undefine(`MY_PGA_CONF') +undefine(`MY_SRC_TOKENS') +undefine(`MY_SRC_CONF')