diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h index 3d74a1ce28bcfe0a559240cdfb73b8c6c8473057..95621de24932b96fbff60e3a72d01c9f078ec70f 100644 --- a/include/sound/q6asm-v2.h +++ b/include/sound/q6asm-v2.h @@ -169,6 +169,7 @@ struct audio_client { /* Relative or absolute TS */ atomic_t time_flag; atomic_t nowait_cmd_cnt; + atomic_t mem_state; void *priv; uint32_t io_mode; uint64_t time_stamp; @@ -180,6 +181,7 @@ struct audio_client { struct audio_port_data port[2]; wait_queue_head_t cmd_wait; wait_queue_head_t time_wait; + wait_queue_head_t mem_wait; int perf_mode; int stream_id; /* audio cache operations fptr*/ diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index 68185cb06d5a845d55c1b1aab5104c10f71a5549..26b96589e40905592465f93b33ae950395e6f74f 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -425,7 +425,7 @@ void send_asm_custom_topology(struct audio_client *ac) q6asm_add_hdr_custom_topology(ac, &asm_top.hdr, APR_PKT_SIZE(APR_HDR_SIZE, sizeof(asm_top)), TRUE); - atomic_set(&ac->cmd_state, 1); + atomic_set(&ac->mem_state, 1); asm_top.hdr.opcode = ASM_CMD_ADD_TOPOLOGIES; asm_top.payload_addr_lsw = lower_32_bits(cal_block.cal_paddr); asm_top.payload_addr_msw = upper_32_bits(cal_block.cal_paddr); @@ -443,8 +443,8 @@ void send_asm_custom_topology(struct audio_client *ac) goto err_unmap; } - result = wait_event_timeout(ac->cmd_wait, - (atomic_read(&ac->cmd_state) == 0), 5*HZ); + result = wait_event_timeout(ac->mem_wait, + (atomic_read(&ac->mem_state) == 0), 5*HZ); if (!result) { pr_err("%s: Set topologies failed payload = 0x%pa\n", __func__, &cal_block.cal_paddr); @@ -864,6 +864,7 @@ struct audio_client *q6asm_audio_client_alloc(app_cb cb, void *priv) init_waitqueue_head(&ac->cmd_wait); init_waitqueue_head(&ac->time_wait); + init_waitqueue_head(&ac->mem_wait); atomic_set(&ac->time_flag, 1); INIT_LIST_HEAD(&ac->port[0].mem_map_handle); INIT_LIST_HEAD(&ac->port[1].mem_map_handle); @@ -875,6 +876,7 @@ struct audio_client *q6asm_audio_client_alloc(app_cb cb, void *priv) } atomic_set(&ac->cmd_state, 0); atomic_set(&ac->nowait_cmd_cnt, 0); + atomic_set(&ac->mem_state, 0); send_asm_custom_topology(ac); @@ -1160,10 +1162,8 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv) atomic_set(&ac->unmap_cb_success, 1); } - if (atomic_read(&ac->cmd_state)) { - atomic_set(&ac->cmd_state, 0); - wake_up(&ac->cmd_wait); - } + if (atomic_cmpxchg(&ac->mem_state, 1, 0)) + wake_up(&ac->mem_wait); pr_debug("%s:Payload = [0x%x] status[0x%x]\n", __func__, payload[0], payload[1]); break; @@ -1183,10 +1183,9 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv) pr_debug("%s:PL#0[0x%x]PL#1 [0x%x] dir=%x s_id=%x\n", __func__, payload[0], payload[1], dir, sid); spin_lock_irqsave(&port->dsp_lock, dsp_flags); - if (atomic_read(&ac->cmd_state)) { + if (atomic_cmpxchg(&ac->mem_state, 1, 0)) { ac->port[dir].tmp_hdl = payload[0]; - atomic_set(&ac->cmd_state, 0); - wake_up(&ac->cmd_wait); + wake_up(&ac->mem_wait); } spin_unlock_irqrestore(&port->dsp_lock, dsp_flags); break; @@ -1195,10 +1194,8 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv) pr_debug("%s:PL#0[0x%x]PL#1 [0x%x]\n", __func__, payload[0], payload[1]); spin_lock_irqsave(&port->dsp_lock, dsp_flags); - if (atomic_read(&ac->cmd_state)) { - atomic_set(&ac->cmd_state, 0); - wake_up(&ac->cmd_wait); - } + if (atomic_cmpxchg(&ac->mem_state, 1, 0)) + wake_up(&ac->mem_wait); spin_unlock_irqrestore(&port->dsp_lock, dsp_flags); break; @@ -1317,7 +1314,6 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) case ASM_STREAM_CMD_OPEN_LOOPBACK_V2: case ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2: case ASM_STREAM_CMD_SET_ENCDEC_PARAM: - case ASM_CMD_ADD_TOPOLOGIES: case ASM_DATA_CMD_REMOVE_INITIAL_SILENCE: case ASM_DATA_CMD_REMOVE_TRAILING_SILENCE: case ASM_SESSION_CMD_REGISTER_FOR_RX_UNDERFLOW_EVENTS: @@ -1332,6 +1328,17 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) ac->cb(data->opcode, data->token, (uint32_t *)data->payload, ac->priv); break; + case ASM_CMD_ADD_TOPOLOGIES: + pr_debug("%s:Payload = [0x%x]stat[0x%x]\n", + __func__, payload[0], payload[1]); + if (atomic_read(&ac->mem_state) && wakeup_flag) { + atomic_set(&ac->mem_state, 0); + wake_up(&ac->mem_wait); + } + if (ac->cb) + ac->cb(data->opcode, data->token, + (uint32_t *)data->payload, ac->priv); + break; case ASM_STREAM_CMD_GET_PP_PARAMS_V2: pr_debug("%s: ASM_STREAM_CMD_GET_PP_PARAMS_V2\n", __func__); @@ -3227,7 +3234,7 @@ int q6asm_memory_map(struct audio_client *ac, phys_addr_t buf_add, int dir, mmap_region_cmd; q6asm_add_mmaphdr(ac, &mmap_regions->hdr, cmd_size, TRUE, ((ac->session << 8) | dir)); - atomic_set(&ac->cmd_state, 1); + atomic_set(&ac->mem_state, 1); mmap_regions->hdr.opcode = ASM_CMD_SHARED_MEM_MAP_REGIONS; mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL; mmap_regions->num_regions = bufcnt & 0x00ff; @@ -3254,8 +3261,8 @@ int q6asm_memory_map(struct audio_client *ac, phys_addr_t buf_add, int dir, goto fail_cmd; } - rc = wait_event_timeout(ac->cmd_wait, - (atomic_read(&ac->cmd_state) == 0 && + rc = wait_event_timeout(ac->mem_wait, + (atomic_read(&ac->mem_state) == 0 && ac->port[dir].tmp_hdl), 5*HZ); if (!rc) { pr_err("timeout. waited for memory_map\n"); @@ -3291,7 +3298,7 @@ int q6asm_memory_unmap(struct audio_client *ac, phys_addr_t buf_add, int dir) q6asm_add_mmaphdr(ac, &mem_unmap.hdr, sizeof(struct avs_cmd_shared_mem_unmap_regions), TRUE, ((ac->session << 8) | dir)); - atomic_set(&ac->cmd_state, 1); + atomic_set(&ac->mem_state, 1); mem_unmap.hdr.opcode = ASM_CMD_SHARED_MEM_UNMAP_REGIONS; mem_unmap.mem_map_handle = 0; list_for_each_safe(ptr, next, &ac->port[dir].mem_map_handle) { @@ -3319,8 +3326,8 @@ int q6asm_memory_unmap(struct audio_client *ac, phys_addr_t buf_add, int dir) goto fail_cmd; } - rc = wait_event_timeout(ac->cmd_wait, - (atomic_read(&ac->cmd_state) == 0), 5 * HZ); + rc = wait_event_timeout(ac->mem_wait, + (atomic_read(&ac->mem_state) == 0), 5 * HZ); if (!rc) { pr_err("%s timeout. waited for memory_unmap of handle 0x%x\n", __func__, mem_unmap.mem_map_handle); @@ -3402,7 +3409,7 @@ static int q6asm_memory_map_regions(struct audio_client *ac, int dir, mmap_region_cmd; q6asm_add_mmaphdr(ac, &mmap_regions->hdr, cmd_size, TRUE, ((ac->session << 8) | dir)); - atomic_set(&ac->cmd_state, 1); + atomic_set(&ac->mem_state, 1); pr_debug("mmap_region=0x%p token=0x%x\n", mmap_regions, ((ac->session << 8) | dir)); @@ -3434,8 +3441,8 @@ static int q6asm_memory_map_regions(struct audio_client *ac, int dir, goto fail_cmd; } - rc = wait_event_timeout(ac->cmd_wait, - (atomic_read(&ac->cmd_state) == 0) + rc = wait_event_timeout(ac->mem_wait, + (atomic_read(&ac->mem_state) == 0) , 5*HZ); if (!rc) { pr_err("timeout. waited for memory_map\n"); @@ -3483,7 +3490,7 @@ static int q6asm_memory_unmap_regions(struct audio_client *ac, int dir) cmd_size = sizeof(struct avs_cmd_shared_mem_unmap_regions); q6asm_add_mmaphdr(ac, &mem_unmap.hdr, cmd_size, TRUE, ((ac->session << 8) | dir)); - atomic_set(&ac->cmd_state, 1); + atomic_set(&ac->mem_state, 1); port = &ac->port[dir]; buf_add = (uint32_t)port->buf->phys; mem_unmap.hdr.opcode = ASM_CMD_SHARED_MEM_UNMAP_REGIONS; @@ -3513,8 +3520,8 @@ static int q6asm_memory_unmap_regions(struct audio_client *ac, int dir) goto fail_cmd; } - rc = wait_event_timeout(ac->cmd_wait, - (atomic_read(&ac->cmd_state) == 0), 5*HZ); + rc = wait_event_timeout(ac->mem_wait, + (atomic_read(&ac->mem_state) == 0), 5*HZ); if (!rc) { pr_err("%s timeout. waited for memory_unmap of handle 0x%x\n", __func__, mem_unmap.mem_map_handle); @@ -4746,6 +4753,7 @@ static int __init q6asm_init(void) common_client.port[1].buf = &common_buf[1]; init_waitqueue_head(&common_client.cmd_wait); init_waitqueue_head(&common_client.time_wait); + init_waitqueue_head(&common_client.mem_wait); atomic_set(&common_client.time_flag, 1); INIT_LIST_HEAD(&common_client.port[0].mem_map_handle); INIT_LIST_HEAD(&common_client.port[1].mem_map_handle); @@ -4756,6 +4764,7 @@ static int __init q6asm_init(void) } atomic_set(&common_client.cmd_state, 0); atomic_set(&common_client.nowait_cmd_cnt, 0); + atomic_set(&common_client.mem_state, 0); config_debug_fs_init();