From 8c749763a56dc43d47a91d3ff4f8b087cb8382b4 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Thu, 25 Mar 2021 17:55:17 +0200 Subject: [PATCH 1/7] audio: codec_adapter: Use generic init_process init_process API is used to initialize the processing phase. (e.g for Cadence: search for valid header, decode header in order to get parameters). init_process needs to have access to the input frames so it will be called by codec adapter copy() function. Signed-off-by: Daniel Baluta --- src/audio/codec_adapter/codec/cadence.c | 4 ---- src/include/sof/audio/codec_adapter/interfaces.h | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/audio/codec_adapter/codec/cadence.c b/src/audio/codec_adapter/codec/cadence.c index 0eac9162d388..0f92059a5bc4 100644 --- a/src/audio/codec_adapter/codec/cadence.c +++ b/src/audio/codec_adapter/codec/cadence.c @@ -399,10 +399,6 @@ int cadence_codec_prepare(struct comp_dev *dev) goto free; } - ret = cadence_codec_init_process(dev); - if (ret) - goto free; - comp_dbg(dev, "cadence_codec_prepare() done"); return 0; free: diff --git a/src/include/sof/audio/codec_adapter/interfaces.h b/src/include/sof/audio/codec_adapter/interfaces.h index 4787ef4d72f4..f333fef7334f 100644 --- a/src/include/sof/audio/codec_adapter/interfaces.h +++ b/src/include/sof/audio/codec_adapter/interfaces.h @@ -36,6 +36,7 @@ static struct codec_interface interfaces[] = { .id = CADENCE_ID, /**< Cadence interface */ .init = cadence_codec_init, .prepare = cadence_codec_prepare, + .init_process = cadence_codec_init_process, .process = cadence_codec_process, .apply_config = cadence_codec_apply_config, .reset = cadence_codec_reset, From 5d8201435135a3b72d661eae6ff751137ce4adfc Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Thu, 25 Mar 2021 17:56:02 +0200 Subject: [PATCH 2/7] audio: codec_adapter: Fix local_buffer size computation local buffer is used to store the output of processing function. So, we need to compute its size based on codec_adapter output buffer not input buffer. For non-compressed processing the current code works because input and output buffer have equal sizes. Signed-off-by: Daniel Baluta --- src/audio/codec_adapter/codec_adapter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio/codec_adapter/codec_adapter.c b/src/audio/codec_adapter/codec_adapter.c index 6413b42021e0..962034781e79 100644 --- a/src/audio/codec_adapter/codec_adapter.c +++ b/src/audio/codec_adapter/codec_adapter.c @@ -245,7 +245,7 @@ static int codec_adapter_prepare(struct comp_dev *dev) } /* Allocate local buffer */ - buff_size = MAX(cd->period_bytes, codec->cpd.in_buff_size) * buff_periods; + buff_size = MAX(cd->period_bytes, codec->cpd.out_buff_size) * buff_periods; if (cd->local_buff) { ret = buffer_set_size(cd->local_buff, buff_size); if (ret < 0) { From 14ad9c256a326a784d713465bebf659291291ae3 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Thu, 25 Mar 2021 18:05:51 +0200 Subject: [PATCH 3/7] audio: codec_adapter: Updated processed bytes processed field keeps the total number of processed bytes from the input buffer. We need to update this field also for the process_init operation. Signed-off-by: Daniel Baluta --- src/audio/codec_adapter/codec_adapter.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/audio/codec_adapter/codec_adapter.c b/src/audio/codec_adapter/codec_adapter.c index 962034781e79..f422699c3766 100644 --- a/src/audio/codec_adapter/codec_adapter.c +++ b/src/audio/codec_adapter/codec_adapter.c @@ -392,6 +392,7 @@ static int codec_adapter_copy(struct comp_dev *dev) return ret; bytes_to_process -= codec->cpd.consumed; + processed += codec->cpd.consumed; comp_update_buffer_consume(source, codec->cpd.consumed); } From f1edc11c7045a2ee8ed594656a1e7f963a72dbdc Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Thu, 25 Mar 2021 18:13:34 +0200 Subject: [PATCH 4/7] audio: codec_adapter: Fix sink bytes copy With compress audio the number of output bytes is usually greater then the number of the input bytes. Because of this, local buffer might have "valid" bytes even if the current process operation didn't produce anything. So, in this period we did not produce anything but we can still copy some bytes from local_buffer to sink buffer. Signed-off-by: Daniel Baluta --- src/audio/codec_adapter/codec_adapter.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/audio/codec_adapter/codec_adapter.c b/src/audio/codec_adapter/codec_adapter.c index f422699c3766..f00355046783 100644 --- a/src/audio/codec_adapter/codec_adapter.c +++ b/src/audio/codec_adapter/codec_adapter.c @@ -431,7 +431,13 @@ static int codec_adapter_copy(struct comp_dev *dev) if (!produced && !cd->deep_buff_bytes) { comp_dbg(dev, "codec_adapter_copy(): nothing processed in this call"); - goto end; + /* we haven't produced anything in this period but we + * still have data in the local buffer to copy to sink + */ + if (audio_stream_get_avail_bytes(&local_buff->stream) >= cd->period_bytes) + goto copy_period; + else + goto end; } else if (!produced && cd->deep_buff_bytes) { goto db_verify; } @@ -451,6 +457,7 @@ static int codec_adapter_copy(struct comp_dev *dev) } } +copy_period: comp_get_copy_limits_with_lock(local_buff, sink, &cl); copy_bytes = cl.frames * cl.source_frame_bytes; audio_stream_copy(&local_buff->stream, 0, From a3245fb87c1cfd583a0c8dcc7f1b480e47eba015 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Thu, 25 Mar 2021 18:14:08 +0200 Subject: [PATCH 5/7] audio: codec_adapter: Make sure local_buff has enough room for processing We need to make sure that the local buffer has enough room to hold the output of the processing. This means that for each type of decoding algorithm we need to know the maximum possible output size and skip processing if local buffer size is less than that. Signed-off-by: Daniel Baluta --- src/audio/codec_adapter/codec_adapter.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/audio/codec_adapter/codec_adapter.c b/src/audio/codec_adapter/codec_adapter.c index f00355046783..10996a491aca 100644 --- a/src/audio/codec_adapter/codec_adapter.c +++ b/src/audio/codec_adapter/codec_adapter.c @@ -406,6 +406,13 @@ static int codec_adapter_copy(struct comp_dev *dev) break; } + /* TODO: remove magic number and use possible maximum output per + * decoding algorithm type + * 9216 is maximum frame length bytes for mp3 at 192Khz, 24bits, + */ + if (local_buff->stream.free < 9217) + goto db_verify; + buffer_invalidate(source, codec_buff_size); codec_adapter_copy_from_source_to_lib(&source->stream, &codec->cpd, codec_buff_size); From 7f21aa879ecd30821d9e7ae4332ad19dadf3c7ba Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Thu, 25 Mar 2021 20:27:00 +0200 Subject: [PATCH 6/7] audio: codec_adapter: Fix processing loop Processing loop inside codec_adapter copy() function will take the input buffer and try to process all the data available. We need to 'consume' the source bytes and 'produce' the bytes to local_buffer after each iteration not just at the end. Failing to do so, will put wrong data for processing function starting with second iteration. Signed-off-by: Daniel Baluta --- src/audio/codec_adapter/codec_adapter.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/audio/codec_adapter/codec_adapter.c b/src/audio/codec_adapter/codec_adapter.c index 10996a491aca..7d826e9381c8 100644 --- a/src/audio/codec_adapter/codec_adapter.c +++ b/src/audio/codec_adapter/codec_adapter.c @@ -434,6 +434,9 @@ static int codec_adapter_copy(struct comp_dev *dev) bytes_to_process -= codec->cpd.consumed; processed += codec->cpd.consumed; produced += codec->cpd.produced; + + audio_stream_produce(&local_buff->stream, codec->cpd.produced); + comp_update_buffer_consume(source, codec->cpd.consumed); } if (!produced && !cd->deep_buff_bytes) { @@ -445,13 +448,8 @@ static int codec_adapter_copy(struct comp_dev *dev) goto copy_period; else goto end; - } else if (!produced && cd->deep_buff_bytes) { - goto db_verify; } - audio_stream_produce(&local_buff->stream, produced); - comp_update_buffer_consume(source, processed); - db_verify: if (cd->deep_buff_bytes) { if (cd->deep_buff_bytes >= audio_stream_get_avail_bytes(&local_buff->stream)) { From ac6c89b9be2d1af87aeec3150310667a086bcad7 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 3 Feb 2021 19:01:09 +0200 Subject: [PATCH 7/7] topology: imx8: Add processing pipeline for i.MX8/i.MX8X Add topology to support compress playback for MP3 on i.MX8/i.MX8X with wm8960 codec. Signed-off-by: Daniel Baluta --- tools/topology/CMakeLists.txt | 1 + tools/topology/sof-imx8-processing-wm8960.m4 | 91 +++++++++++++++++++ .../sof/pipe-codec-adapter-playback.m4 | 4 +- 3 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 tools/topology/sof-imx8-processing-wm8960.m4 diff --git a/tools/topology/CMakeLists.txt b/tools/topology/CMakeLists.txt index cce80a38dcd9..2e7f309656bd 100644 --- a/tools/topology/CMakeLists.txt +++ b/tools/topology/CMakeLists.txt @@ -129,6 +129,7 @@ set(TPLGS "sof-jsl-da7219\;sof-jsl-da7219\;-DPLATFORM=jsl" "sof-jsl-da7219\;sof-jsl-da7219-mx98360a\;-DPLATFORM=jsl-dedede" "sof-imx8mp-wm8960\;sof-imx8mp-wm8960" + "sof-imx8-processing-wm8960\;sof-imx8-processing-wm8960\;-DPP_CORE=0" "sof-smart-amplifier-nocodec\;sof-smart-amplifier-nocodec" "sof-jsl-rt5682\;sof-jsl-rt5682-rt1015\;-DPLATFORM=jsl-rt1015" "sof-jsl-rt5682\;sof-jsl-rt5682-mx98360a\;-DPLATFORM=jsl-dedede" diff --git a/tools/topology/sof-imx8-processing-wm8960.m4 b/tools/topology/sof-imx8-processing-wm8960.m4 new file mode 100644 index 000000000000..ccf222d27eb1 --- /dev/null +++ b/tools/topology/sof-imx8-processing-wm8960.m4 @@ -0,0 +1,91 @@ +# +# Topology with codec_adapter processing component for i.MX8QM/i.MX8QXP +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`sai.m4') +include(`pcm.m4') +include(`buffer.m4') + +# Include TLV library +include(`common/tlv.m4') + +# Include Token library +include(`sof/tokens.m4') + +# Include DSP configuration +include(`platform/imx/imx8qxp.m4') + + +# Post process setup config + + #codec Post Process setup config +# +# Define the pipelines +# +# PCM0 <----> volume <-----> SAI3 (wm8960) +# + + ++# Post process setup config +define(`CA_SETUP_CONTROLBYTES', +`` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x20,0x00,0x00,0x00,0x00,0x10,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x06,0x01,0xDE,0xCA,0x00,0x00,0x00,0x00,' +` 0x80,0xBB,0x00,0x00,0x20,0x00,0x00,0x00,' +` 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x0C,0x00,0x00,0x00,0x20,0x00,0x00,0x00"'' +) + +define(`CA_SETUP_CONTROLBYTES_MAX', 300) + +undefine(`DAI_PERIODS') +define(`DAI_PERIODS', 16) + +dnl PIPELINE_PCM_ADD(pipeline, +dnl pipe id, pcm, max channels, format, +dnl period, priority, core, +dnl pcm_min_rate, pcm_max_rate, pipeline_rate, +dnl time_domain, sched_comp) + +# Low Latency playback pipeline 1 on PCM 0 using max 2 channels of s32le. +# Set 1000us deadline on core 0 with priority 0 +PIPELINE_PCM_ADD(sof/pipe-codec-adapter-playback.m4, + 1, 0, 2, s32le, + 1000, 0, 0, + 48000, 48000, 48000) + +# +# DAIs configuration +# + +dnl DAI_ADD(pipeline, +dnl pipe id, dai type, dai_index, dai_be, +dnl buffer, periods, format, +dnl period, priority, core, time_domain) + +# playback DAI is SAI3 using 2 periods +# Buffers use s32le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-playback.m4, + 1, SAI, 1, sai1-wm8960-hifi, + PIPELINE_SOURCE_1, 2, s32le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + + +# PCM Low Latency, id 0 + +dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) +COMPR_PLAYBACK_ADD(Port0, 0, PIPELINE_PCM_1) + +dnl DAI_CONFIG(type, idx, link_id, name, sai_config) +DAI_CONFIG(SAI, 1, 0, sai1-wm8960-hifi, + SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), + SAI_CLOCK(bclk, 3072000, codec_master), + SAI_CLOCK(fsync, 48000, codec_master), + SAI_TDM(2, 32, 3, 3), + SAI_CONFIG_DATA(SAI, 1, 0))) diff --git a/tools/topology/sof/pipe-codec-adapter-playback.m4 b/tools/topology/sof/pipe-codec-adapter-playback.m4 index af3c5e4c1b98..9619fb1f16b4 100644 --- a/tools/topology/sof/pipe-codec-adapter-playback.m4 +++ b/tools/topology/sof/pipe-codec-adapter-playback.m4 @@ -115,10 +115,10 @@ W_CODEC_ADAPTER(0, PIPELINE_FORMAT, DAI_PERIODS, DAI_PERIODS, CA_SCHEDULE_CORE, LIST(` ', "CA_SETUP_CONTROLBYTES_NAME_PIPE", "CA_RUNTIME_CONTROLBYTES_NAME_PIPE")) # Playback Buffers -W_BUFFER(0, COMP_BUFFER_SIZE(DAI_PERIODS, +W_BUFFER(0, COMP_BUFFER_SIZE(8, COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_HOST_MEM_CAP, SCHEDULE_CORE) -W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, +W_BUFFER(1, COMP_BUFFER_SIZE(2, COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_DAI_MEM_CAP, SCHEDULE_CORE)