From baa791f6e10b96ec2f31d3ec39a10ecba31c35ef Mon Sep 17 00:00:00 2001 From: Seppo Ingalsuo Date: Thu, 6 Sep 2018 13:00:17 +0300 Subject: [PATCH 1/2] Topology: Add Equalizer This patch adds EQ, bytecontrol, and EQ+volume pipeline m4 macros and an enhanced topology with EQ for UP2 + HiFiberry. There is not yet FIR/IIR type select. The EQ type is currently hardcoded into kernel. Signed-off-by: Seppo Ingalsuo Signed-off-by: Ranjani Sridharan Signed-off-by: Jaska Uimonen --- topology/Makefile.am | 6 +- topology/m4/bytecontrol.m4 | 54 ++++++++++++ topology/m4/eq.m4 | 43 ++++++++++ topology/sof-apl-eq-pcm512x.m4 | 55 ++++++++++++ topology/sof/pipe-eq-volume-playback.m4 | 88 ++++++++++++++++++++ topology/test/test-equalizer-playback-ssp.m4 | 74 ++++++++++++++++ 6 files changed, 318 insertions(+), 2 deletions(-) create mode 100644 topology/m4/bytecontrol.m4 create mode 100644 topology/m4/eq.m4 create mode 100644 topology/sof-apl-eq-pcm512x.m4 create mode 100644 topology/sof/pipe-eq-volume-playback.m4 create mode 100644 topology/test/test-equalizer-playback-ssp.m4 diff --git a/topology/Makefile.am b/topology/Makefile.am index 207e520..3e466df 100644 --- a/topology/Makefile.am +++ b/topology/Makefile.am @@ -35,7 +35,8 @@ MACHINES = \ sof-apl-wm8804.tplg \ sof-apl-da7219.tplg \ sof-glk-da7219.tplg \ - sof-icl-nocodec.tplg + sof-icl-nocodec.tplg \ + sof-apl-eq-pcm512x.tplg # Uncomment the following line if you want to debug conf files .PRECIOUS: %.conf @@ -71,4 +72,5 @@ EXTRA_DIST = \ sof-apl-wm8804.m4 \ sof-apl-da7219.m4 \ sof-glk-da7219.m4 \ - sof-icl-nocodec.m4 + sof-icl-nocodec.m4 \ + sof-apl-eq-pcm512x.m4 diff --git a/topology/m4/bytecontrol.m4 b/topology/m4/bytecontrol.m4 new file mode 100644 index 0000000..d36b93f --- /dev/null +++ b/topology/m4/bytecontrol.m4 @@ -0,0 +1,54 @@ +divert(-1) + +dnl Define macro for byte control + +dnl CONTROLBYTES_MAX(comment, value) +define(`CONTROLBYTES_MAX', +`#$1' +` max STR($2)') + +dnl CONTROLMIXER_TLV(comment, value) +define(`CONTROLBYTES_TLV', +`#$1' +` tlv STR($2)') + +dnl CONTROLMIXER_OPS(info, comment, get, put) +define(`CONTROLBYTES_OPS', +`ops."ctl" {' +` info STR($1)' +` #$2' +` }') + +dnl CONTROLMIXER_OPS(info, comment, get, put) +define(`CONTROLBYTES_EXTOPS', +`extops."extctl" {' +` #$1' +` get STR($2)' +` put STR($3)' +` }') + +dnl C_CONTROLMIXER(name, index, ops, base, num_regs, mask, max, tlv) +define(`C_CONTROLBYTES', +`SectionControlBytes.STR($1) {' +`' +` # control belongs to this index group' +` index STR($2)' +`' +` # control uses bespoke driver get/put/info ID for io ops' +` $3' +` # control uses bespoke driver get/put/info ID for ext ops' +` $4' +`' +` base STR($5)' +` num_regs STR($6)' +` mask STR($7)' +` $8' +` $9' +` access [' +` tlv_write' +` tlv_read' +` tlv_callback' +` ]' +`}') + +divert(0)dnl diff --git a/topology/m4/eq.m4 b/topology/m4/eq.m4 new file mode 100644 index 0000000..d9efee3 --- /dev/null +++ b/topology/m4/eq.m4 @@ -0,0 +1,43 @@ +divert(-1) + +dnl Define macro for Eq effect widget + +dnl EQ name) +define(`N_EQ', `EQ'PIPELINE_ID`.'$1) + +dnl W_EQ(name, format, periods_sink, periods_source, preload, kcontrols_list) +define(`W_EQ', +`SectionVendorTuples."'N_EQ($1)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` SOF_TKN_COMP_PRELOAD_COUNT' STR($5) +` }' +`}' +`SectionData."'N_EQ($1)`_data_w" {' +` tuples "'N_EQ($1)`_tuples_w"' +`}' +`SectionVendorTuples."'N_EQ($1)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($2) +` }' +`}' +`SectionData."'N_EQ($1)`_data_str" {' +` tuples "'N_EQ($1)`_tuples_str"' +`}' +`SectionWidget."'N_EQ($1)`" {' +` index "'PIPELINE_ID`"' +` type "effect"' +` no_pm "true"' +` data [' +` "'N_EQ($1)`_data_w"' +` "'N_EQ($1)`_data_str"' +` ]' +` bytes [' + $6 +` ]' +`}') + +divert(0)dnl diff --git a/topology/sof-apl-eq-pcm512x.m4 b/topology/sof-apl-eq-pcm512x.m4 new file mode 100644 index 0000000..f1fda8d --- /dev/null +++ b/topology/sof-apl-eq-pcm512x.m4 @@ -0,0 +1,55 @@ +# +# Topology for generic Apollolake UP^2 with pcm512x codec. +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`ssp.m4') + +# Include TLV library +include(`common/tlv.m4') + +# Include Token library +include(`sof/tokens.m4') + +# Include Apollolake DSP configuration +include(`platform/intel/bxt.m4') + +# +# Define the pipelines +# +# PCM0 ----> volume -----> SSP5 (pcm512x) +# + +# Low Latency playback pipeline 1 on PCM 0 using max 2 channels of s32le. +# Schedule 48 frames per 1000us deadline on core 0 with priority 0 +PIPELINE_PCM_ADD(sof/pipe-eq-volume-playback.m4, + 1, 0, 2, s32le, + 48, 1000, 0, 0) + +# +# DAIs configuration +# + +# playback DAI is SSP5 using 2 periods +# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-playback.m4, + 1, SSP, 5, SSP5-Codec, + PIPELINE_SOURCE_1, 2, s24le, + 48, 1000, 0, 0) + +# PCM Low Latency, id 0 +PCM_PLAYBACK_ADD(Port5, 0, PIPELINE_PCM_1) + +# +# BE configurations - overrides config in ACPI if present +# + +DAI_CONFIG(SSP, 5, 0, SSP5-Codec, + SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24576000, codec_mclk_in), + SSP_CLOCK(bclk, 3072000, codec_slave), + SSP_CLOCK(fsync, 48000, codec_slave), + SSP_TDM(2, 32, 3, 3), + SSP_CONFIG_DATA(SSP, 5, 24))) diff --git a/topology/sof/pipe-eq-volume-playback.m4 b/topology/sof/pipe-eq-volume-playback.m4 new file mode 100644 index 0000000..4b7cb32 --- /dev/null +++ b/topology/sof/pipe-eq-volume-playback.m4 @@ -0,0 +1,88 @@ +# Low Latency Passthrough with volume Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> EQ 0 --> B1 --> Volume 0 --> B2 --> sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`mixercontrol.m4') +include(`bytecontrol.m4') +include(`pipeline.m4') +include(`eq.m4') + +# +# Controls +# +# Volume Mixer control with max value of 32 +C_CONTROLMIXER(Master Playback Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 256 binds the mixer control to volume get/put handlers, 256, 256), + CONTROLMIXER_MAX(, 32), + false, + CONTROLMIXER_TLV(TLV 32 steps from -90dB to +6dB for 3dB, vtlv_m90s3), + Channel register and shift for Front Left/Right, + LIST(` ', KCONTROL_CHANNEL(FL, 1, 0), KCONTROL_CHANNEL(FR, 1, 1))) + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(EQ, 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(, 10)) + +# +# Components and Buffers +# + +# Host "Passthrough Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Passthrough Playback, 2, 0, 2) + +# "Volume" has 2 source and 2 sink periods +W_PGA(0, PIPELINE_FORMAT, 2, 2, 2, LIST(` ', "Master Playback Volume PIPELINE_ID")) + +# "EQ 0" has 2 sink period and 2 source periods +W_EQ(0, PIPELINE_FORMAT, 2, 2, 2, LIST(` ', "EQ")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, SCHEDULE_FRAMES), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, SCHEDULE_FRAMES), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, SCHEDULE_FRAMES), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P --> B0 --> EQ 0 --> B1 --> Volume 0 --> B2 --> sink DAI0 + +P_GRAPH(pipe-pass-vol-playback-PIPELINE_ID, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMP(PCM_ID), Passthrough Playback PCM_ID)', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_EQ(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_EQ(0))', + `dapm(N_PGA(0), N_BUFFER(1))', + `dapm(N_BUFFER(2), N_PGA(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Playback PCM_ID) + + +# +# PCM Configuration + +# +PCM_CAPABILITIES(Passthrough Playback PCM_ID, `S32_LE,S24_LE,S16_LE', 48000, 48000, 2, 8, 2, 16, 192, 16384, 65536, 65536) + diff --git a/topology/test/test-equalizer-playback-ssp.m4 b/topology/test/test-equalizer-playback-ssp.m4 new file mode 100644 index 0000000..ab775a4 --- /dev/null +++ b/topology/test/test-equalizer-playback-ssp.m4 @@ -0,0 +1,74 @@ +# +# Topology for pass through pipeline +# + +# Include topology builder +include(`pipeline.m4') +include(`dai.m4') +include(`utils.m4') + +# Include TLV library +include(`common/tlv.m4') + +# Include Token library +include(`sof/tokens.m4') + +# Include Baytrail DSP configuration +include(`dsps/byt.m4') + +# +# Machine Specific Config - !! MUST BE SET TO MATCH TEST MACHINE DRIVER !! +# +# TEST_PIPE_NAME - Pipe name +# TEST_DAI_LINK_NAME - BE DAI link name e.g. "NoCodec" +# TEST_SSP_PORT - SSP port number e.g. 2 +# TEST_SSP_FORMAT - SSP data format e.g s16le +# TEST_PIPE_FORMAT - Pipeline format e.g. s16le +# TEST_SSP_MCLK - SSP MCLK in Hz +# TEST_SSP_BCLK - SSP BCLK in Hz +# TEST_SSP_PHY_BITS - SSP physical slot size +# TEST_SSP_DATA_BITS - SSP data slot size +# + +# +# Define the pipeline +# +# PCM0 <---> SSP TEST_SSP_PORT +# + +# Passthrough playback pipeline 1 on PCM 0 using max 2 channels of s24le. +# Schedule 48 frames per 1000us deadline on core 0 with priority 0 +# Use DMAC 0 channel 1 for PCM audio playback data + +PIPELINE_PCM_DAI_ADD(sof/pipe-TEST_PIPE_NAME-playback.m4, + 1, 0, 2, TEST_PIPE_FORMAT, + 48, 1000, 0, 0, 0, 1, + SSP, TEST_SSP_PORT, TEST_SSP_FORMAT, 2) +# +# DAI configuration +# +# SSP port TEST_SSP_PORT is our only pipeline DAI +# + +# playback DAI is SSP TEST_SSP_PORT using 2 periods +# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-playback.m4, + 1, SSP, TEST_SSP_PORT, TEST_DAI_LINK_NAME, + PIPELINE_SOURCE_1, 2, TEST_SSP_FORMAT, + 48, 1000, 0, 0) + +# PCM Passthrough +PCM_PLAYBACK_ADD(Passthrough, 3, 0, 0, PIPELINE_PCM_1) + +# +# BE configurations - overrides config in ACPI if present +# +# Clocks masters wrt codec +# +# TEST_SSP_DATA_BITS bit I2S using TEST_SSP_PHY_BITS bit sample conatiner on SSP TEST_SSP_PORT +# +DAI_CONFIG(SSP, TEST_SSP_PORT, TEST_DAI_LINK_NAME, I2S, TEST_SSP_DATA_BITS, + DAI_CLOCK(mclk, TEST_SSP_MCLK, slave), + DAI_CLOCK(bclk, TEST_SSP_BCLK, slave), + DAI_CLOCK(fsync, 48000, slave), + DAI_TDM(2, TEST_SSP_PHY_BITS, 3, 3)) From 6b56dafe305b1f2725084ca3a81db114230af336 Mon Sep 17 00:00:00 2001 From: Jaska Uimonen Date: Sun, 9 Sep 2018 19:22:42 +0300 Subject: [PATCH 2/2] Topology: Add generic type string to effect widgets data field Adding type string to widget data allows the driver to identify different effects. As an example use this in the equalizer. Also modify equalizer to pass default parameters in control's private data. Signed-off-by: Jaska Uimonen --- topology/m4/bytecontrol.m4 | 10 +- topology/m4/eq.m4 | 43 --------- topology/m4/eq_fir.m4 | 53 ++++++++++ topology/m4/eq_iir.m4 | 53 ++++++++++ topology/sof/pipe-eq-fir-volume-playback.m4 | 97 +++++++++++++++++++ topology/sof/pipe-eq-iir-volume-playback.m4 | 101 ++++++++++++++++++++ topology/sof/pipe-eq-volume-playback.m4 | 61 +++++++++--- topology/sof/tokens.m4 | 4 + 8 files changed, 366 insertions(+), 56 deletions(-) delete mode 100644 topology/m4/eq.m4 create mode 100644 topology/m4/eq_fir.m4 create mode 100644 topology/m4/eq_iir.m4 create mode 100644 topology/sof/pipe-eq-fir-volume-playback.m4 create mode 100644 topology/sof/pipe-eq-iir-volume-playback.m4 diff --git a/topology/m4/bytecontrol.m4 b/topology/m4/bytecontrol.m4 index d36b93f..22a7b6f 100644 --- a/topology/m4/bytecontrol.m4 +++ b/topology/m4/bytecontrol.m4 @@ -27,7 +27,12 @@ define(`CONTROLBYTES_EXTOPS', ` put STR($3)' ` }') -dnl C_CONTROLMIXER(name, index, ops, base, num_regs, mask, max, tlv) +define(`CONTROLBYTES_PRIV', +`SectionData.STR($1) {' +` $2' +`}') + +dnl C_CONTROLMIXER(name, index, ops, base, num_regs, mask, max, tlv, priv) define(`C_CONTROLBYTES', `SectionControlBytes.STR($1) {' `' @@ -49,6 +54,9 @@ define(`C_CONTROLBYTES', ` tlv_read' ` tlv_callback' ` ]' +` data [' +` $10' +` ]' `}') divert(0)dnl diff --git a/topology/m4/eq.m4 b/topology/m4/eq.m4 deleted file mode 100644 index d9efee3..0000000 --- a/topology/m4/eq.m4 +++ /dev/null @@ -1,43 +0,0 @@ -divert(-1) - -dnl Define macro for Eq effect widget - -dnl EQ name) -define(`N_EQ', `EQ'PIPELINE_ID`.'$1) - -dnl W_EQ(name, format, periods_sink, periods_source, preload, kcontrols_list) -define(`W_EQ', -`SectionVendorTuples."'N_EQ($1)`_tuples_w" {' -` tokens "sof_comp_tokens"' -` tuples."word" {' -` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) -` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) -` SOF_TKN_COMP_PRELOAD_COUNT' STR($5) -` }' -`}' -`SectionData."'N_EQ($1)`_data_w" {' -` tuples "'N_EQ($1)`_tuples_w"' -`}' -`SectionVendorTuples."'N_EQ($1)`_tuples_str" {' -` tokens "sof_comp_tokens"' -` tuples."string" {' -` SOF_TKN_COMP_FORMAT' STR($2) -` }' -`}' -`SectionData."'N_EQ($1)`_data_str" {' -` tuples "'N_EQ($1)`_tuples_str"' -`}' -`SectionWidget."'N_EQ($1)`" {' -` index "'PIPELINE_ID`"' -` type "effect"' -` no_pm "true"' -` data [' -` "'N_EQ($1)`_data_w"' -` "'N_EQ($1)`_data_str"' -` ]' -` bytes [' - $6 -` ]' -`}') - -divert(0)dnl diff --git a/topology/m4/eq_fir.m4 b/topology/m4/eq_fir.m4 new file mode 100644 index 0000000..75d1d9f --- /dev/null +++ b/topology/m4/eq_fir.m4 @@ -0,0 +1,53 @@ +divert(-1) + +dnl Define macro for Eq effect widget + +dnl EQ name) +define(`N_EQ_FIR', `EQFIR'PIPELINE_ID`.'$1) + +dnl W_EQ(name, format, periods_sink, periods_source, preload, kcontrols_list) +define(`W_EQ_FIR', +`SectionVendorTuples."'N_EQ_FIR($1)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` SOF_TKN_COMP_PRELOAD_COUNT' STR($5) +` }' +`}' +`SectionData."'N_EQ_FIR($1)`_data_w" {' +` tuples "'N_EQ_FIR($1)`_tuples_w"' +`}' +`SectionVendorTuples."'N_EQ_FIR($1)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($2) +` }' +`}' +`SectionData."'N_EQ_FIR($1)`_data_str" {' +` tuples "'N_EQ_FIR($1)`_tuples_str"' +`}' +`SectionVendorTuples."'N_EQ_FIR($1)`_tuples_str_type" {' +` tokens "sof_effect_tokens"' +` tuples."string" {' +` SOF_TKN_EFFECT_TYPE' "EQFIR" +` }' +`}' +`SectionData."'N_EQ_FIR($1)`_data_str_type" {' +` tuples "'N_EQ_FIR($1)`_tuples_str_type"' +`}' +`SectionWidget."'N_EQ_FIR($1)`" {' +` index "'PIPELINE_ID`"' +` type "effect"' +` no_pm "true"' +` data [' +` "'N_EQ_FIR($1)`_data_w"' +` "'N_EQ_FIR($1)`_data_str"' +` "'N_EQ_FIR($1)`_data_str_type"' +` ]' +` bytes [' + $6 +` ]' +`}') + +divert(0)dnl diff --git a/topology/m4/eq_iir.m4 b/topology/m4/eq_iir.m4 new file mode 100644 index 0000000..1f6466b --- /dev/null +++ b/topology/m4/eq_iir.m4 @@ -0,0 +1,53 @@ +divert(-1) + +dnl Define macro for Eq effect widget + +dnl EQ name) +define(`N_EQ_IIR', `EQIIR'PIPELINE_ID`.'$1) + +dnl W_EQ(name, format, periods_sink, periods_source, preload, kcontrols_list) +define(`W_EQ_IIR', +`SectionVendorTuples."'N_EQ_IIR($1)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` SOF_TKN_COMP_PRELOAD_COUNT' STR($5) +` }' +`}' +`SectionData."'N_EQ_IIR($1)`_data_w" {' +` tuples "'N_EQ_IIR($1)`_tuples_w"' +`}' +`SectionVendorTuples."'N_EQ_IIR($1)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($2) +` }' +`}' +`SectionData."'N_EQ_IIR($1)`_data_str" {' +` tuples "'N_EQ_IIR($1)`_tuples_str"' +`}' +`SectionVendorTuples."'N_EQ_IIR($1)`_tuples_str_type" {' +` tokens "sof_effect_tokens"' +` tuples."string" {' +` SOF_TKN_EFFECT_TYPE' "EQIIR" +` }' +`}' +`SectionData."'N_EQ_IIR($1)`_data_str_type" {' +` tuples "'N_EQ_IIR($1)`_tuples_str_type"' +`}' +`SectionWidget."'N_EQ_IIR($1)`" {' +` index "'PIPELINE_ID`"' +` type "effect"' +` no_pm "true"' +` data [' +` "'N_EQ_IIR($1)`_data_w"' +` "'N_EQ_IIR($1)`_data_str"' +` "'N_EQ_IIR($1)`_data_str_type"' +` ]' +` bytes [' + $6 +` ]' +`}') + +divert(0)dnl diff --git a/topology/sof/pipe-eq-fir-volume-playback.m4 b/topology/sof/pipe-eq-fir-volume-playback.m4 new file mode 100644 index 0000000..da66d6c --- /dev/null +++ b/topology/sof/pipe-eq-fir-volume-playback.m4 @@ -0,0 +1,97 @@ +# Low Latency Passthrough with volume Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> EQ 0 --> B1 --> Volume 0 --> B2 --> sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`mixercontrol.m4') +include(`bytecontrol.m4') +include(`pipeline.m4') +include(`eq_fir.m4') + +# +# Controls +# +# Volume Mixer control with max value of 32 +C_CONTROLMIXER(Master Playback Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 256 binds the mixer control to volume get/put handlers, 256, 256), + CONTROLMIXER_MAX(, 32), + false, + CONTROLMIXER_TLV(TLV 32 steps from -90dB to +6dB for 3dB, vtlv_m90s3), + Channel register and shift for Front Left/Right, + LIST(` ', KCONTROL_CHANNEL(FL, 1, 0), KCONTROL_CHANNEL(FR, 1, 1))) + +# EQ initial parameters, in this case flat response +CONTROLBYTES_PRIV(EQFIR_priv, +` bytes "0x18,0x00,0x00,0x00,0x02,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00"' +) + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(EQFIR, 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(, 316), + , + EQFIR_priv) + +# +# Components and Buffers +# + +# Host "Passthrough Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Passthrough Playback, 2, 0, 2) + +# "Volume" has 2 source and 2 sink periods +W_PGA(0, PIPELINE_FORMAT, 2, 2, 2, LIST(` ', "Master Playback Volume PIPELINE_ID")) + +# "EQ 0" has 2 sink period and 2 source periods +W_EQ_FIR(0, PIPELINE_FORMAT, 2, 2, 2, LIST(` ', "EQFIR")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, SCHEDULE_FRAMES), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, SCHEDULE_FRAMES), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, SCHEDULE_FRAMES), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P --> B0 --> EQ 0 --> B1 --> Volume 0 --> B2 --> sink DAI0 + +P_GRAPH(pipe-pass-vol-playback-PIPELINE_ID, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMP(PCM_ID), Passthrough Playback PCM_ID)', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_EQ_FIR(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_EQ_FIR(0))', + `dapm(N_PGA(0), N_BUFFER(1))', + `dapm(N_BUFFER(2), N_PGA(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Playback PCM_ID) + + +# +# PCM Configuration + +# +PCM_CAPABILITIES(Passthrough Playback PCM_ID, `S32_LE,S24_LE,S16_LE', 48000, 48000, 2, 8, 2, 16, 192, 16384, 65536, 65536) + diff --git a/topology/sof/pipe-eq-iir-volume-playback.m4 b/topology/sof/pipe-eq-iir-volume-playback.m4 new file mode 100644 index 0000000..3b93f3c --- /dev/null +++ b/topology/sof/pipe-eq-iir-volume-playback.m4 @@ -0,0 +1,101 @@ +# Low Latency Passthrough with volume Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> EQ 0 --> B1 --> Volume 0 --> B2 --> sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`mixercontrol.m4') +include(`bytecontrol.m4') +include(`pipeline.m4') +include(`eq_iir.m4') + +# +# Controls +# +# Volume Mixer control with max value of 32 +C_CONTROLMIXER(Master Playback Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 256 binds the mixer control to volume get/put handlers, 256, 256), + CONTROLMIXER_MAX(, 32), + false, + CONTROLMIXER_TLV(TLV 32 steps from -90dB to +6dB for 3dB, vtlv_m90s3), + Channel register and shift for Front Left/Right, + LIST(` ', KCONTROL_CHANNEL(FL, 1, 0), KCONTROL_CHANNEL(FR, 1, 1))) + +# EQ initial parameters, in this case flat response +CONTROLBYTES_PRIV(EQIIR_priv, +` bytes "0x38,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x01,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,0x9e,0x73,0x13,0x20,' +` 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00"' +) + +# 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), + , , , + CONTROLBYTES_MAX(, 316), + , + EQIIR_priv) + +# +# Components and Buffers +# + +# Host "Passthrough Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Passthrough Playback, 2, 0, 2) + +# "Volume" has 2 source and 2 sink periods +W_PGA(0, PIPELINE_FORMAT, 2, 2, 2, LIST(` ', "Master Playback Volume PIPELINE_ID")) + +# "EQ 0" has 2 sink period and 2 source periods +W_EQ_IIR(0, PIPELINE_FORMAT, 2, 2, 2, LIST(` ', "EQIIR")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, SCHEDULE_FRAMES), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, SCHEDULE_FRAMES), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, SCHEDULE_FRAMES), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P --> B0 --> EQ 0 --> B1 --> Volume 0 --> B2 --> sink DAI0 + +P_GRAPH(pipe-pass-vol-playback-PIPELINE_ID, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMP(PCM_ID), Passthrough Playback PCM_ID)', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_EQ_IIR(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_EQ_IIR(0))', + `dapm(N_PGA(0), N_BUFFER(1))', + `dapm(N_BUFFER(2), N_PGA(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Playback PCM_ID) + + +# +# PCM Configuration + +# +PCM_CAPABILITIES(Passthrough Playback PCM_ID, `S32_LE,S24_LE,S16_LE', 48000, 48000, 2, 8, 2, 16, 192, 16384, 65536, 65536) + diff --git a/topology/sof/pipe-eq-volume-playback.m4 b/topology/sof/pipe-eq-volume-playback.m4 index 4b7cb32..c3ca5b7 100644 --- a/topology/sof/pipe-eq-volume-playback.m4 +++ b/topology/sof/pipe-eq-volume-playback.m4 @@ -2,7 +2,7 @@ # # Pipeline Endpoints for connection are :- # -# host PCM_P --> B0 --> EQ 0 --> B1 --> Volume 0 --> B2 --> sink DAI0 +# host PCM_P --> B0 --> EQ_IIR 0 --> B1 --> EQ_FIR 0 --> B2 --> Volume 0 --> B3 --> sink DAI0 # Include topology builder include(`utils.m4') @@ -13,7 +13,8 @@ include(`dai.m4') include(`mixercontrol.m4') include(`bytecontrol.m4') include(`pipeline.m4') -include(`eq.m4') +include(`eq_iir.m4') +include(`eq_fir.m4') # # Controls @@ -27,12 +28,41 @@ C_CONTROLMIXER(Master Playback Volume, PIPELINE_ID, Channel register and shift for Front Left/Right, LIST(` ', KCONTROL_CHANNEL(FL, 1, 0), KCONTROL_CHANNEL(FR, 1, 1))) +# EQ initial parameters, in this case flat response +CONTROLBYTES_PRIV(EQIIR_priv, +` bytes "0x38,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x01,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,0x9e,0x73,0x13,0x20,' +` 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00"' +) + # EQ Bytes control with max value of 255 -C_CONTROLBYTES(EQ, PIPELINE_ID, +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), , , , - CONTROLBYTES_MAX(, 10)) + CONTROLBYTES_MAX(, 316), + , + EQIIR_priv) + +# EQ initial parameters, in this case flat response +CONTROLBYTES_PRIV(EQFIR_priv, +` bytes "0x18,0x00,0x00,0x00,0x02,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00"' +) + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(EQFIR, 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(, 316), + , + EQFIR_priv) # # Components and Buffers @@ -46,7 +76,10 @@ W_PCM_PLAYBACK(PCM_ID, Passthrough Playback, 2, 0, 2) W_PGA(0, PIPELINE_FORMAT, 2, 2, 2, LIST(` ', "Master Playback Volume PIPELINE_ID")) # "EQ 0" has 2 sink period and 2 source periods -W_EQ(0, PIPELINE_FORMAT, 2, 2, 2, LIST(` ', "EQ")) +W_EQ_IIR(0, PIPELINE_FORMAT, 2, 2, 2, LIST(` ', "EQIIR")) + +# "EQ 0" has 2 sink period and 2 source periods +W_EQ_FIR(0, PIPELINE_FORMAT, 2, 2, 2, LIST(` ', "EQFIR")) # Playback Buffers W_BUFFER(0, COMP_BUFFER_SIZE(2, @@ -56,30 +89,34 @@ W_BUFFER(1, COMP_BUFFER_SIZE(2, COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, SCHEDULE_FRAMES), PLATFORM_HOST_MEM_CAP) W_BUFFER(2, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, SCHEDULE_FRAMES), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(3, COMP_BUFFER_SIZE(2, COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, SCHEDULE_FRAMES), PLATFORM_DAI_MEM_CAP) # # Pipeline Graph # -# host PCM_P --> B0 --> EQ 0 --> B1 --> Volume 0 --> B2 --> sink DAI0 +# host host PCM_P --> B0 --> EQ_IIR 0 --> B1 --> EQ_FIR 0 --> B2 --> Volume 0 --> B3 --> sink DAI0 P_GRAPH(pipe-pass-vol-playback-PIPELINE_ID, PIPELINE_ID, LIST(` ', `dapm(N_PCMP(PCM_ID), Passthrough Playback PCM_ID)', `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', - `dapm(N_EQ(0), N_BUFFER(0))', - `dapm(N_BUFFER(1), N_EQ(0))', - `dapm(N_PGA(0), N_BUFFER(1))', - `dapm(N_BUFFER(2), N_PGA(0))')) + `dapm(N_EQ_IIR(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_EQ_IIR(0))', + `dapm(N_EQ_FIR(0), N_BUFFER(1))', + `dapm(N_BUFFER(2), N_EQ_FIR(0))', + `dapm(N_PGA(0), N_BUFFER(2))', + `dapm(N_BUFFER(3), N_PGA(0))')) # # Pipeline Source and Sinks # -indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(3)) indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Playback PCM_ID) - # # PCM Configuration diff --git a/topology/sof/tokens.m4 b/topology/sof/tokens.m4 index 4aa2fea..b584f56 100644 --- a/topology/sof/tokens.m4 +++ b/topology/sof/tokens.m4 @@ -82,3 +82,7 @@ SectionVendorTokens."sof_dmic_pdm_tokens" { SectionVendorTokens."sof_tone_tokens" { SOF_TKN_TONE_SAMPLE_RATE "800" } + +SectionVendorTokens."sof_effect_tokens" { + SOF_TKN_EFFECT_TYPE "900" +}