diff --git a/tools/topology/m4/eq_iir_coef_highpass_50hz_20db_16khz.m4 b/tools/topology/m4/eq_iir_coef_highpass_50hz_20db_16khz.m4 new file mode 100644 index 000000000000..40aba6f8ba4d --- /dev/null +++ b/tools/topology/m4/eq_iir_coef_highpass_50hz_20db_16khz.m4 @@ -0,0 +1,18 @@ +# 50 Hz second order high-pass and +20 dB gain 13-Aug-2019 +CONTROLBYTES_PRIV(EQIIR_HP50HZ20dB16K_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x57,0xb1,0xc0,0xc1,' +` 0xd2,0x13,0x39,0x7e,0x45,0x3b,0xa2,0x1f,' +` 0x76,0x89,0xbb,0xc0,0x45,0x3b,0xa2,0x1f,' +` 0xfc,0xff,0xff,0xff,0xd0,0x4f,0x00,0x00"' +) diff --git a/tools/topology/m4/eq_iir_coef_highpass_50hz_20db_48khz.m4 b/tools/topology/m4/eq_iir_coef_highpass_50hz_20db_48khz.m4 index 40d1e90eab7d..d22924ef5a55 100644 --- a/tools/topology/m4/eq_iir_coef_highpass_50hz_20db_48khz.m4 +++ b/tools/topology/m4/eq_iir_coef_highpass_50hz_20db_48khz.m4 @@ -1,5 +1,5 @@ # 50 Hz second order high-pass and +20 dB gain 18-Dec-2018 -CONTROLBYTES_PRIV(EQIIR_priv, +CONTROLBYTES_PRIV(EQIIR_HP50HZ20dB48K_priv, ` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' ` 0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x03,' ` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' diff --git a/tools/topology/platform/intel/intel-generic-dmic.m4 b/tools/topology/platform/intel/intel-generic-dmic.m4 index 34648e1f0cbb..56b758c82fd8 100644 --- a/tools/topology/platform/intel/intel-generic-dmic.m4 +++ b/tools/topology/platform/intel/intel-generic-dmic.m4 @@ -19,14 +19,16 @@ dnl pcm_min_rate, pcm_max_rate, pipeline_rate, dnl time_domain, sched_comp) # Passthrough capture pipeline using max channels defined by CHANNELS. + # Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, +PIPELINE_PCM_ADD(sof/pipe-eq-capture.m4, DMIC_PIPELINE_48k_ID, DMIC_DAI_LINK_48k_ID, CHANNELS, s32le, 1000, 0, 0, 48000, 48000, 48000) # Passthrough capture pipeline using max channels defined by CHANNELS. + # Schedule with 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture-16khz.m4, +PIPELINE_PCM_ADD(sof/pipe-eq-capture-16khz.m4, DMIC_PIPELINE_16k_ID, DMIC_DAI_LINK_16k_ID, CHANNELS, s32le, 1000, 0, 0, 16000, 16000, 16000) @@ -66,11 +68,11 @@ dnl DAI_CONFIG(type, dai_index, link_id, name, ssp_config/dmic_config) ifelse(CHANNELS, 4, `DAI_CONFIG(DMIC, 0, DMIC_DAI_LINK_48k_ID, dmic01, DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, + DMIC_WORD_LENGTH(s32le), 200, DMIC, 0, PDM_CONFIG(DMIC, 0, FOUR_CH_PDM0_PDM1)))', `DAI_CONFIG(DMIC, 0, DMIC_DAI_LINK_48k_ID, dmic01, DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, + DMIC_WORD_LENGTH(s32le), 200, DMIC, 0, PDM_CONFIG(DMIC, 0, STEREO_PDM0)))') ifelse(CHANNELS, 4, diff --git a/tools/topology/sof/pipe-eq-capture-16khz.m4 b/tools/topology/sof/pipe-eq-capture-16khz.m4 new file mode 100644 index 000000000000..4cdafff62b82 --- /dev/null +++ b/tools/topology/sof/pipe-eq-capture-16khz.m4 @@ -0,0 +1,108 @@ +# Capture EQ Pipeline and PCM, 16 kHz +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <-- Volume 0 <-- B1 <--EQ_IIR 0 <-- B2 <-- sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`bytecontrol.m4') +include(`eq_iir.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(, 70), + false, + CONTROLMIXER_TLV(TLV 80 steps from -50dB to +20dB 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 +W_VENDORTUPLES(capture_pga_tokens, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) + +W_DATA(capture_pga_conf, capture_pga_tokens) + +# Use 50 Hz highpass response with +20 dB gain +include(`eq_iir_coef_highpass_50hz_20db_16khz.m4') + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(EQIIR_C16, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + CONTROLBYTES_EXTOPS( + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + , , , + CONTROLBYTES_MAX(, 304), + , + EQIIR_HP50HZ20dB16K_priv) + +# +# Components and Buffers +# + +# Host "Highpass Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, Highpass Capture, 0, 2) + +# "Volume" has 2 source and 2 sink periods +W_PGA(0, PIPELINE_FORMAT, 2, 2, + capture_pga_conf, LIST(` ', + "PIPELINE_ID Master Capture Volume")) + +# "EQ 0" has 2 sink period and 2 source periods +W_EQ_IIR(0, PIPELINE_FORMAT, 2, 2, LIST(` ', "EQIIR_C16")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + eval(PCM_MAX_RATE / SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + eval(PCM_MAX_RATE / SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(2, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + eval(PCM_MAX_RATE / SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_C <-- B0 <-- Volume 0 <-- B1 <--EQ_IIR 0 <-- B2 <-- sink DAI0 + +P_GRAPH(pipe-pass-capture-PIPELINE_ID, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), N_PGA(0))', + `dapm(N_PGA(0), N_BUFFER(1))', + `dapm(N_BUFFER(1), N_EQ_IIR(0))', + `dapm(N_EQ_IIR(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), Highpass Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(Highpass Capture PCM_ID, `S32_LE,S24_LE,S16_LE', 16000, 16000, + PIPELINE_CHANNELS, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) diff --git a/tools/topology/sof/pipe-eq-capture.m4 b/tools/topology/sof/pipe-eq-capture.m4 index 3b266d571c11..e82db2bbd3a7 100644 --- a/tools/topology/sof/pipe-eq-capture.m4 +++ b/tools/topology/sof/pipe-eq-capture.m4 @@ -1,33 +1,57 @@ -# Capture EQ Pipeline and PCM +# Capture EQ Pipeline and PCM, 48 kHz # # Pipeline Endpoints for connection are :- # -# host PCM_C <--- B1 <--- EQ_IIR 0 <-- B0 <-- sink DAI0 +# host PCM_C <-- B0 <-- Volume 0 <-- B1 <--EQ_IIR 0 <-- B2 <-- sink DAI0 # Include topology builder include(`utils.m4') include(`buffer.m4') include(`pcm.m4') +include(`pga.m4') include(`dai.m4') include(`pipeline.m4') include(`bytecontrol.m4') +include(`mixercontrol.m4') include(`eq_iir.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(, 70), + false, + CONTROLMIXER_TLV(TLV 80 steps from -50dB to +20dB 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 +W_VENDORTUPLES(capture_pga_tokens, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) + +W_DATA(capture_pga_conf, capture_pga_tokens) + # Use 50 Hz highpass response with +20 dB gain include(`eq_iir_coef_highpass_50hz_20db_48khz.m4') # EQ Bytes control with max value of 255 -C_CONTROLBYTES(EQIIR, PIPELINE_ID, - CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), - CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), +C_CONTROLBYTES(EQIIR_C48, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + CONTROLBYTES_EXTOPS( + 258 binds the mixer control to bytes get/put handlers, + 258, 258), , , , CONTROLBYTES_MAX(, 304), , - EQIIR_priv) + EQIIR_HP50HZ20dB48K_priv) # # Components and Buffers @@ -37,37 +61,50 @@ C_CONTROLBYTES(EQIIR, PIPELINE_ID, # with 0 sink and 2 source periods W_PCM_CAPTURE(PCM_ID, Highpass Capture, 0, 2) +# "Volume" has 2 source and 2 sink periods +W_PGA(0, PIPELINE_FORMAT, 2, 2, + capture_pga_conf, LIST(` ', + "PIPELINE_ID Master Capture Volume")) + # "EQ 0" has 2 sink period and 2 source periods -W_EQ_IIR(0, PIPELINE_FORMAT, 2, 2, LIST(` ', "EQIIR")) +W_EQ_IIR(0, PIPELINE_FORMAT, 2, 2, LIST(` ', "EQIIR_C48")) # Capture Buffers W_BUFFER(0, COMP_BUFFER_SIZE(2, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, eval(PCM_MAX_RATE / SCHEDULE_PERIOD)), - PLATFORM_PASS_MEM_CAP) + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + eval(PCM_MAX_RATE / SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) W_BUFFER(1, COMP_BUFFER_SIZE(2, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, eval(PCM_MAX_RATE / SCHEDULE_PERIOD)), - PLATFORM_PASS_MEM_CAP) + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + eval(PCM_MAX_RATE / SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(2, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + eval(PCM_MAX_RATE / SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) # # Pipeline Graph # -# host PCM_C <--- B1 <--- EQ_IIR 0 <-- B0 <-- sink DAI0 +# host PCM_C <-- B0 <-- Volume 0 <-- B1 <--EQ_IIR 0 <-- B2 <-- sink DAI0 P_GRAPH(pipe-pass-capture-PIPELINE_ID, PIPELINE_ID, LIST(` ', - `dapm(N_PCMC(PCM_ID), N_BUFFER(1))', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), N_PGA(0))', + `dapm(N_PGA(0), N_BUFFER(1))', `dapm(N_BUFFER(1), N_EQ_IIR(0))', - `dapm(N_EQ_IIR(0), N_BUFFER(0))')) + `dapm(N_EQ_IIR(0), N_BUFFER(2))')) # # Pipeline Source and Sinks # -indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(0)) +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(2)) indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Highpass Capture PCM_ID) # # PCM Configuration # -PCM_CAPABILITIES(Highpass Capture PCM_ID, `S32_LE,S24_LE,S16_LE', PCM_MIN_RATE, PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) +PCM_CAPABILITIES(Highpass Capture PCM_ID, `S32_LE,S24_LE,S16_LE', PCM_MIN_RATE, + PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) diff --git a/tools/topology/sof/pipe-volume-capture-16khz.m4 b/tools/topology/sof/pipe-volume-capture-16khz.m4 index 2ffb76dff851..1c68751c370a 100644 --- a/tools/topology/sof/pipe-volume-capture-16khz.m4 +++ b/tools/topology/sof/pipe-volume-capture-16khz.m4 @@ -78,4 +78,6 @@ indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Capture PCM_ID # PCM Configuration # -PCM_CAPABILITIES(Passthrough Capture PCM_ID, `S32_LE,S24_LE,S16_LE', 16000, 16000, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) +PCM_CAPABILITIES(Passthrough Capture PCM_ID, `S32_LE,S24_LE,S16_LE', + 16000, 16000, PIPELINE_CHANNELS, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) diff --git a/tools/topology/sof/pipe-volume-capture.m4 b/tools/topology/sof/pipe-volume-capture.m4 index 9685f071a89d..e7e7c61f8b7f 100644 --- a/tools/topology/sof/pipe-volume-capture.m4 +++ b/tools/topology/sof/pipe-volume-capture.m4 @@ -75,5 +75,6 @@ indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough 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(Passthrough Capture PCM_ID, `S32_LE,S24_LE,S16_LE', + PCM_MIN_RATE, PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) diff --git a/tools/tune/eq/example_iir_eq.m b/tools/tune/eq/example_iir_eq.m index 5f89c1782dee..496bc280fa2b 100644 --- a/tools/tune/eq/example_iir_eq.m +++ b/tools/tune/eq/example_iir_eq.m @@ -39,7 +39,7 @@ function example_iir_eq() %% ------------------- %% Example 1: Loudness %% ------------------- -alsa_fn = '../../eqctl/eq_iir_loudness.txt'; +alsa_fn = '../../ctl/eq_iir_loudness.txt'; blob_fn = 'example_iir_eq.blob'; tplg_fn = 'example_iir_eq.m4'; @@ -71,7 +71,7 @@ function example_iir_eq() %% ------------------------------------ %% Example 2: Bass boost %% ------------------------------------ -alsa_fn = '../../eqctl/eq_iir_bassboost.txt'; +alsa_fn = '../../ctl/eq_iir_bassboost.txt'; %% Design IIR bass boost equalizer eq_bass = bassboost_iir_eq(fs); @@ -95,7 +95,7 @@ function example_iir_eq() %% ------------------------------------ %% Example 3: Band-pass %% ------------------------------------ -alsa_fn = '../../eqctl/eq_iir_bandpass.txt'; +alsa_fn = '../../ctl/eq_iir_bandpass.txt'; %% Design IIR bass boost equalizer eq_band = bandpass_iir_eq(fs); @@ -131,21 +131,23 @@ function example_iir_eq() %% Build blob channels_in_config = 2; % Setup max 2 channels EQ assign_response = [0 0]; % Switch to response #0 -num_responses = 1; % One responses: bass +num_responses = 1; % One responses: hp bm = eq_iir_blob_merge(channels_in_config, ... num_responses, ... assign_response, ... bq_hp); -%% Pack and write file +%% Pack and write file. If there are several EQ instances need +%% to have identifier string to get correct response to each +%% instance (here _HP50HZ20dB48K) and refer to in topology. bp = eq_iir_blob_pack(bm); -eq_tplg_write(tplg_fn, bp, 'IIR', comment); +eq_tplg_write(tplg_fn, bp, 'IIR_HP50HZ20dB48K', comment); %% ------------------- %% Example 5: Flat IIR %% ------------------- comment = 'Flat IIR EQ'; -alsa_fn = '../../eqctl/eq_iir_flat.txt'; +alsa_fn = '../../ctl/eq_iir_flat.txt'; tplg_fn = '../../topology/m4/eq_iir_coef_flat.m4'; %% Define a passthru IIR EQ equalizer @@ -171,7 +173,7 @@ function example_iir_eq() %% --------------------------- %% Example 6: Pass-through IIR %% ------------------------------------ -alsa_fn = '../../eqctl/eq_iir_pass.txt'; +alsa_fn = '../../ctl/eq_iir_pass.txt'; %% Define a passthru IIR EQ equalizer [z_pass, p_pass, k_pass] = tf2zp([1 0 0],[1 0 0]); @@ -192,6 +194,33 @@ function example_iir_eq() bp = eq_iir_blob_pack(bm); eq_alsactl_write(alsa_fn, bp); +%% -------------------------------------------- +%% Example 7: 50 Hz high-pass with gain, 16 kHz +%% -------------------------------------------- +tplg_fn = '../../topology/m4/eq_iir_coef_highpass_50hz_20db_16khz.m4'; +comment = '50 Hz second order high-pass and +20 dB gain'; + +%% Design IIR high-pass +eq_hp = hp_iir_eq(16e3); + +%% Quantize and pack filter coefficients plus shifts etc. +bq_hp = eq_iir_blob_quant(eq_hp.p_z, eq_hp.p_p, eq_hp.p_k); + +%% Build blob +channels_in_config = 2; % Setup max 2 channels EQ +assign_response = [0 0]; % Switch to response #0 +num_responses = 1; % One response: hp +bm = eq_iir_blob_merge(channels_in_config, ... + num_responses, ... + assign_response, ... + bq_hp); + +%% Pack and write file. If there are several EQ instances need +%% to have identifier string to get correct response to each +%% instance (here _HP50HZ20dB16K) and refer to in topology. +bp = eq_iir_blob_pack(bm); +eq_tplg_write(tplg_fn, bp, 'IIR_HP50HZ20dB16K', comment); + end %% -------------------