From 073dc502072108ba29db9dbed025da774020dd0e Mon Sep 17 00:00:00 2001 From: Piotr Makaruk Date: Mon, 23 Jan 2023 12:16:02 +0100 Subject: [PATCH 1/2] hda: chain transition states fix Require maintenance in logic to handle multiple start/pause requests by one chain instance. Signed-off-by: Piotr Makaruk --- src/audio/chain_dma.c | 205 ++++++++++++++++++++++-------------------- 1 file changed, 108 insertions(+), 97 deletions(-) diff --git a/src/audio/chain_dma.c b/src/audio/chain_dma.c index f815b7c6b4f0..fdb2038e389e 100644 --- a/src/audio/chain_dma.c +++ b/src/audio/chain_dma.c @@ -120,99 +120,6 @@ static int chain_host_stop(struct comp_dev *dev) return 0; } -static int chain_task_start(struct comp_dev *dev) -{ - struct comp_driver_list *drivers = comp_drivers_get(); - struct chain_dma_data *cd = comp_get_drvdata(dev); - k_spinlock_key_t key; - int ret; - - comp_info(dev, "chain_task_start(), host_dma_id = 0x%08x", cd->host_connector_node_id.dw); - - key = k_spin_lock(&drivers->lock); - switch (cd->chain_task.state) { - case SOF_TASK_STATE_QUEUED: - k_spin_unlock(&drivers->lock, key); - return 0; - case SOF_TASK_STATE_COMPLETED: - break; - case SOF_TASK_STATE_INIT: - break; - default: - comp_err(dev, "chain_task_start(), bad state transition"); - ret = -EINVAL; - goto error; - } - - if (cd->stream_direction == SOF_IPC_STREAM_PLAYBACK) { - ret = chain_host_start(dev); - if (ret) - goto error; - ret = chain_link_start(dev); - if (ret) { - chain_host_stop(dev); - goto error; - } - } else { - ret = chain_link_start(dev); - if (ret) - goto error; - ret = chain_host_start(dev); - if (ret) { - chain_link_stop(dev); - goto error; - } - } - - pm_policy_state_lock_get(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES); - - ret = schedule_task(&cd->chain_task, 0, 0); - if (ret) { - chain_host_stop(dev); - chain_link_stop(dev); - goto error; - } - - cd->chain_task.state = SOF_TASK_STATE_INIT; - -error: - k_spin_unlock(&drivers->lock, key); - return ret; -} - -static int chain_task_pause(struct comp_dev *dev) -{ - struct comp_driver_list *drivers = comp_drivers_get(); - struct chain_dma_data *cd = comp_get_drvdata(dev); - k_spinlock_key_t key; - int ret, ret2; - - if (cd->chain_task.state == SOF_TASK_STATE_FREE) - return 0; - - key = k_spin_lock(&drivers->lock); - cd->first_data_received = false; - if (cd->stream_direction == SOF_IPC_STREAM_PLAYBACK) { - ret = chain_host_stop(dev); - ret2 = chain_link_stop(dev); - } else { - ret = chain_link_stop(dev); - ret2 = chain_host_stop(dev); - } - if (!ret) - ret = ret2; - if (ret < 0) - goto error; - - cd->chain_task.state = SOF_TASK_STATE_COMPLETED; - schedule_task_free(&cd->chain_task); - pm_policy_state_lock_put(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES); - -error: - k_spin_unlock(&drivers->lock, key); - return ret; -} - /* Get size of data, which was consumed by link */ static size_t chain_get_transferred_data_size(const uint32_t out_read_pos, const uint32_t in_read_pos, const size_t buff_size) @@ -333,6 +240,114 @@ static enum task_state chain_task_run(void *data) return SOF_TASK_STATE_RESCHEDULE; } +static int chain_task_start(struct comp_dev *dev) +{ + struct comp_driver_list *drivers = comp_drivers_get(); + struct chain_dma_data *cd = comp_get_drvdata(dev); + k_spinlock_key_t key; + int ret; + + comp_info(dev, "chain_task_start(), host_dma_id = 0x%08x", cd->host_connector_node_id.dw); + + key = k_spin_lock(&drivers->lock); + switch (cd->chain_task.state) { + case SOF_TASK_STATE_QUEUED: + k_spin_unlock(&drivers->lock, key); + return 0; + case SOF_TASK_STATE_COMPLETED: + break; + case SOF_TASK_STATE_INIT: + break; + case SOF_TASK_STATE_FREE: + break; + default: + comp_err(dev, "chain_task_start(), bad state transition"); + ret = -EINVAL; + goto error; + } + + if (cd->stream_direction == SOF_IPC_STREAM_PLAYBACK) { + ret = chain_host_start(dev); + if (ret) + goto error; + ret = chain_link_start(dev); + if (ret) { + chain_host_stop(dev); + goto error; + } + } else { + ret = chain_link_start(dev); + if (ret) + goto error; + ret = chain_host_start(dev); + if (ret) { + chain_link_stop(dev); + goto error; + } + } + + pm_policy_state_lock_get(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES); + + ret = schedule_task_init_ll(&cd->chain_task, SOF_UUID(chain_dma_uuid), + SOF_SCHEDULE_LL_TIMER, SOF_TASK_PRI_HIGH, + chain_task_run, cd, 0, 0); + if (ret < 0) { + comp_err(dev, "chain_task_start(), ll task initialization failed"); + rfree(&cd->chain_task); + goto error_task; + } + + ret = schedule_task(&cd->chain_task, 0, 0); + if (ret) + goto error_task; + + cd->chain_task.state = SOF_TASK_STATE_INIT; + k_spin_unlock(&drivers->lock, key); + + return 0; + +error_task: + pm_policy_state_lock_put(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES); + chain_host_stop(dev); + chain_link_stop(dev); +error: + k_spin_unlock(&drivers->lock, key); + return ret; +} + +static int chain_task_pause(struct comp_dev *dev) +{ + struct comp_driver_list *drivers = comp_drivers_get(); + struct chain_dma_data *cd = comp_get_drvdata(dev); + k_spinlock_key_t key; + int ret, ret2; + + if (cd->chain_task.state == SOF_TASK_STATE_FREE) + return 0; + + key = k_spin_lock(&drivers->lock); + cd->first_data_received = false; + if (cd->stream_direction == SOF_IPC_STREAM_PLAYBACK) { + ret = chain_host_stop(dev); + ret2 = chain_link_stop(dev); + } else { + ret = chain_link_stop(dev); + ret2 = chain_host_stop(dev); + } + if (!ret) + ret = ret2; + if (ret < 0) + goto error; + + cd->chain_task.state = SOF_TASK_STATE_COMPLETED; + schedule_task_free(&cd->chain_task); + +error: + pm_policy_state_lock_put(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES); + k_spin_unlock(&drivers->lock, key); + return ret; +} + static void chain_release(struct comp_dev *dev) { struct chain_dma_data *cd = comp_get_drvdata(dev); @@ -461,10 +476,6 @@ static int chain_task_init(struct comp_dev *dev, uint8_t host_dma_id, uint8_t li uint32_t dir; int ret; - schedule_task_init_ll(&cd->chain_task, SOF_UUID(chain_dma_uuid), - SOF_SCHEDULE_LL_TIMER, SOF_TASK_PRI_HIGH, - chain_task_run, cd, 0, 0); - ret = get_connector_node_id(host_dma_id, true, &cd->host_connector_node_id); if (ret < 0) return ret; From b82162685d3417db2a5dad1c39bf4f9e49c42795 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 23 Jan 2023 16:06:40 +0200 Subject: [PATCH 2/2] Revert "topology2: avs-tplg: disable USE_CHAIN_DMA" This reverts commit c3807ae4a7617314b753ae7713200e3ae918e039. Re-enable ChainDMA on TGL for testing. Signed-off-by: Peter Ujfalusi --- tools/topology/topology2/avs-tplg/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/topology/topology2/avs-tplg/CMakeLists.txt b/tools/topology/topology2/avs-tplg/CMakeLists.txt index 906768c508ff..d0bbf64f5497 100644 --- a/tools/topology/topology2/avs-tplg/CMakeLists.txt +++ b/tools/topology/topology2/avs-tplg/CMakeLists.txt @@ -3,17 +3,17 @@ # Array of "input-file-name;output-file-name;comma separated pre-processor variables" set(TPLGS # CAVS HDMI only topology with passthrough pipelines -"sof-hda-generic\;sof-hda-generic-idisp\;USE_CHAIN_DMA=false,DEEPBUFFER_FW_DMA_MS=100" +"sof-hda-generic\;sof-hda-generic-idisp\;USE_CHAIN_DMA=true,DEEPBUFFER_FW_DMA_MS=100" # CAVS HDA topology with mixer-based pipelines for HDA and passthrough pipelines for HDMI -"sof-hda-generic\;sof-hda-generic\;HDA_CONFIG=mix,USE_CHAIN_DMA=false,DEEPBUFFER_FW_DMA_MS=100" +"sof-hda-generic\;sof-hda-generic\;HDA_CONFIG=mix,USE_CHAIN_DMA=true,DEEPBUFFER_FW_DMA_MS=100" # If the alsatplg plugins for NHLT are not available, the NHLT blobs will not be added to the # topologies below. "sof-hda-generic\;sof-hda-generic-2ch\;\ -HDA_CONFIG=mix,NUM_DMICS=2,PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-2ch.bin,USE_CHAIN_DMA=false,\ +HDA_CONFIG=mix,NUM_DMICS=2,PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-2ch.bin,USE_CHAIN_DMA=true,\ DEEPBUFFER_FW_DMA_MS=100" "sof-hda-generic\;sof-hda-generic-4ch\;\ HDA_CONFIG=mix,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,\ -PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-4ch.bin,USE_CHAIN_DMA=false,DEEPBUFFER_FW_DMA_MS=100" +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-4ch.bin,USE_CHAIN_DMA=true,DEEPBUFFER_FW_DMA_MS=100" # CAVS SDW topology with passthrough pipelines "cavs-sdw\;cavs-sdw\;DEEPBUFFER_FW_DMA_MS=100,\ PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-cavs-sdw.bin"