diff --git a/src/audio/chain_dma.c b/src/audio/chain_dma.c index f815b7c6b4f0..e2465404c9be 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,109 @@ 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; + } + } + + 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"); + goto error_task; + } + + ret = schedule_task(&cd->chain_task, 0, 0); + if (ret < 0) { + comp_err(dev, "chain_task_start(), ll schedule task failed"); + schedule_task_free(&cd->chain_task); + goto error_task; + } + + pm_policy_state_lock_get(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES); + cd->chain_task.state = SOF_TASK_STATE_INIT; + k_spin_unlock(&drivers->lock, key); + + return 0; + +error_task: + 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; + + schedule_task_free(&cd->chain_task); + 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 +471,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;