Loading include/sound/q6asm-v2.h +3 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include <sound/apr_audio-v2.h> #include <linux/list.h> #include <linux/msm_ion.h> #include <linux/spinlock.h> #define IN 0x000 #define OUT 0x001 Loading Loading @@ -173,6 +174,8 @@ struct audio_client { /* Relative or absolute TS */ atomic_t time_flag; atomic_t nowait_cmd_cnt; struct list_head no_wait_que; spinlock_t no_wait_que_spinlock; atomic_t mem_state; void *priv; uint32_t io_mode; Loading sound/soc/msm/qdsp6v2/q6asm.c +81 −18 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ #include <linux/dma-mapping.h> #include <linux/miscdevice.h> #include <linux/delay.h> #include <linux/spinlock.h> #include <linux/slab.h> #include <linux/msm_audio.h> Loading Loading @@ -64,6 +63,11 @@ static struct asm_mmap this_mmap; /* session id: 0 reserved */ static struct audio_client *session[SESSION_MAX+1]; struct asm_no_wait_node { struct list_head list; int32_t opcode; }; struct asm_buffer_node { struct list_head list; phys_addr_t buf_phys_addr; Loading Loading @@ -429,6 +433,54 @@ static void q6asm_session_free(struct audio_client *ac) return; } static int q6asm_add_nowait_opcode(struct audio_client *ac, uint32_t opcode) { struct asm_no_wait_node *new_node; unsigned long flags; int ret = 0; new_node = kmalloc(sizeof(struct asm_no_wait_node), GFP_ATOMIC); if (new_node == NULL) { ret = -ENOMEM; goto done; } new_node->opcode = opcode; INIT_LIST_HEAD(&new_node->list); spin_lock_irqsave(&ac->no_wait_que_spinlock, flags); list_add_tail(&new_node->list, &ac->no_wait_que); spin_unlock_irqrestore(&ac->no_wait_que_spinlock, flags); done: return ret; } static bool q6asm_remove_nowait_opcode(struct audio_client *ac, uint32_t opcode) { struct list_head *ptr, *next; struct asm_no_wait_node *node; unsigned long flags; bool ret = false; spin_lock_irqsave(&ac->no_wait_que_spinlock, flags); list_for_each_safe(ptr, next, &ac->no_wait_que) { node = list_entry(ptr, struct asm_no_wait_node, list); if (node->opcode == opcode) { list_del(&node->list); kfree(node); ret = true; goto done; } } pr_err("%s: nowait opcode NOT found 0x%x\n", __func__, opcode); done: spin_unlock_irqrestore(&ac->no_wait_que_spinlock, flags); return ret; } static uint32_t q6asm_get_next_buf(struct audio_client *ac, uint32_t curr_buf, uint32_t max_buf_cnt) { Loading Loading @@ -899,6 +951,9 @@ void q6asm_audio_client_free(struct audio_client *ac) { int loopcnt; struct audio_port_data *port; struct list_head *ptr, *next; struct asm_no_wait_node *node; if (!ac) { pr_err("%s: ac %p\n", __func__, ac); return; Loading @@ -922,6 +977,13 @@ void q6asm_audio_client_free(struct audio_client *ac) } } list_for_each_safe(ptr, next, &ac->no_wait_que) { node = list_entry(ptr, struct asm_no_wait_node, list); list_del(&node->list); kfree(node); } list_del(&ac->no_wait_que); apr_deregister(ac->apr2); ac->apr2 = NULL; apr_deregister(ac->apr); Loading Loading @@ -1060,6 +1122,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); INIT_LIST_HEAD(&ac->no_wait_que); atomic_set(&ac->mem_state, 0); rc = send_asm_custom_topology(ac); Loading Loading @@ -1435,29 +1498,18 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv) return 0; } static int32_t is_no_wait_cmd_rsp(uint32_t opcode, uint32_t *cmd_type) static bool remove_no_wait_cmd(struct audio_client *ac, uint32_t opcode, uint32_t *cmd_type) { if (opcode == APR_BASIC_RSP_RESULT) { if (cmd_type != NULL) { switch (cmd_type[0]) { case ASM_SESSION_CMD_RUN_V2: case ASM_SESSION_CMD_PAUSE: case ASM_DATA_CMD_EOS: case ASM_DATA_CMD_REMOVE_INITIAL_SILENCE: case ASM_DATA_CMD_REMOVE_TRAILING_SILENCE: case ASM_STREAM_CMD_SET_PP_PARAMS_V2: return 1; default: pr_debug("%s: default err 0x%x\n", __func__, cmd_type[0]); break; } return q6asm_remove_nowait_opcode(ac, cmd_type[0]); } else pr_err("%s: null pointer!", __func__); } else if (opcode == ASM_DATA_EVENT_RENDERED_EOS) return 1; return q6asm_remove_nowait_opcode(ac, ASM_DATA_CMD_EOS); return 0; return false; } static void q6asm_process_mtmx_get_param_rsp(struct audio_client *ac, Loading Loading @@ -1545,7 +1597,7 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) payload = data->payload; if ((atomic_read(&ac->nowait_cmd_cnt) > 0) && is_no_wait_cmd_rsp(data->opcode, payload)) { remove_no_wait_cmd(ac, data->opcode, payload)) { pr_debug("%s: nowait_cmd_cnt %d\n", __func__, atomic_read(&ac->nowait_cmd_cnt)); Loading Loading @@ -2837,9 +2889,11 @@ static int __q6asm_run_nowait(struct audio_client *ac, uint32_t flags, /* have to increase first avoid race */ atomic_inc(&ac->nowait_cmd_cnt); q6asm_add_nowait_opcode(ac, run.hdr.opcode); rc = apr_send_pkt(ac->apr, (uint32_t *) &run); if (rc < 0) { atomic_dec(&ac->nowait_cmd_cnt); q6asm_remove_nowait_opcode(ac, run.hdr.opcode); pr_err("%s: Commmand run failed[%d]", __func__, rc); return -EINVAL; } Loading Loading @@ -6265,9 +6319,11 @@ static int __q6asm_cmd_nowait(struct audio_client *ac, int cmd, hdr.opcode); /* have to increase first avoid race */ atomic_inc(&ac->nowait_cmd_cnt); q6asm_add_nowait_opcode(ac, hdr.opcode); rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr); if (rc < 0) { atomic_dec(&ac->nowait_cmd_cnt); q6asm_remove_nowait_opcode(ac, hdr.opcode); pr_err("%s: Commmand 0x%x failed %d\n", __func__, hdr.opcode, rc); goto fail_cmd; Loading Loading @@ -6323,10 +6379,12 @@ int __q6asm_send_meta_data(struct audio_client *ac, uint32_t stream_id, silence.num_samples_to_remove = initial_samples; atomic_inc(&ac->nowait_cmd_cnt); q6asm_add_nowait_opcode(ac, silence.hdr.opcode); rc = apr_send_pkt(ac->apr, (uint32_t *) &silence); if (rc < 0) { pr_err("%s: Commmand silence failed[%d]", __func__, rc); atomic_dec(&ac->nowait_cmd_cnt); q6asm_remove_nowait_opcode(ac, silence.hdr.opcode); goto fail_cmd; } Loading @@ -6334,10 +6392,12 @@ int __q6asm_send_meta_data(struct audio_client *ac, uint32_t stream_id, silence.num_samples_to_remove = trailing_samples; atomic_inc(&ac->nowait_cmd_cnt); q6asm_add_nowait_opcode(ac, silence.hdr.opcode); rc = apr_send_pkt(ac->apr, (uint32_t *) &silence); if (rc < 0) { pr_err("%s: Commmand silence failed[%d]", __func__, rc); atomic_dec(&ac->nowait_cmd_cnt); q6asm_remove_nowait_opcode(ac, silence.hdr.opcode); goto fail_cmd; } Loading Loading @@ -6837,10 +6897,12 @@ static int q6asm_send_asm_cal_nowait(struct audio_client *ac) payload_params.data_payload_size); atomic_inc(&ac->nowait_cmd_cnt); q6asm_add_nowait_opcode(ac, hdr.opcode); rc = apr_send_pkt(ac->apr, (uint32_t *) asm_params); if (rc < 0) { pr_err("%s: audio audstrm cal send failed\n", __func__); atomic_dec(&ac->nowait_cmd_cnt); q6asm_remove_nowait_opcode(ac, hdr.opcode); rc = -EINVAL; goto done; } Loading Loading @@ -7060,6 +7122,7 @@ static int __init q6asm_init(void) } atomic_set(&common_client.cmd_state, 0); atomic_set(&common_client.nowait_cmd_cnt, 0); INIT_LIST_HEAD(&common_client.no_wait_que); atomic_set(&common_client.mem_state, 0); ret = q6asm_init_cal_data(); Loading Loading
include/sound/q6asm-v2.h +3 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include <sound/apr_audio-v2.h> #include <linux/list.h> #include <linux/msm_ion.h> #include <linux/spinlock.h> #define IN 0x000 #define OUT 0x001 Loading Loading @@ -173,6 +174,8 @@ struct audio_client { /* Relative or absolute TS */ atomic_t time_flag; atomic_t nowait_cmd_cnt; struct list_head no_wait_que; spinlock_t no_wait_que_spinlock; atomic_t mem_state; void *priv; uint32_t io_mode; Loading
sound/soc/msm/qdsp6v2/q6asm.c +81 −18 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ #include <linux/dma-mapping.h> #include <linux/miscdevice.h> #include <linux/delay.h> #include <linux/spinlock.h> #include <linux/slab.h> #include <linux/msm_audio.h> Loading Loading @@ -64,6 +63,11 @@ static struct asm_mmap this_mmap; /* session id: 0 reserved */ static struct audio_client *session[SESSION_MAX+1]; struct asm_no_wait_node { struct list_head list; int32_t opcode; }; struct asm_buffer_node { struct list_head list; phys_addr_t buf_phys_addr; Loading Loading @@ -429,6 +433,54 @@ static void q6asm_session_free(struct audio_client *ac) return; } static int q6asm_add_nowait_opcode(struct audio_client *ac, uint32_t opcode) { struct asm_no_wait_node *new_node; unsigned long flags; int ret = 0; new_node = kmalloc(sizeof(struct asm_no_wait_node), GFP_ATOMIC); if (new_node == NULL) { ret = -ENOMEM; goto done; } new_node->opcode = opcode; INIT_LIST_HEAD(&new_node->list); spin_lock_irqsave(&ac->no_wait_que_spinlock, flags); list_add_tail(&new_node->list, &ac->no_wait_que); spin_unlock_irqrestore(&ac->no_wait_que_spinlock, flags); done: return ret; } static bool q6asm_remove_nowait_opcode(struct audio_client *ac, uint32_t opcode) { struct list_head *ptr, *next; struct asm_no_wait_node *node; unsigned long flags; bool ret = false; spin_lock_irqsave(&ac->no_wait_que_spinlock, flags); list_for_each_safe(ptr, next, &ac->no_wait_que) { node = list_entry(ptr, struct asm_no_wait_node, list); if (node->opcode == opcode) { list_del(&node->list); kfree(node); ret = true; goto done; } } pr_err("%s: nowait opcode NOT found 0x%x\n", __func__, opcode); done: spin_unlock_irqrestore(&ac->no_wait_que_spinlock, flags); return ret; } static uint32_t q6asm_get_next_buf(struct audio_client *ac, uint32_t curr_buf, uint32_t max_buf_cnt) { Loading Loading @@ -899,6 +951,9 @@ void q6asm_audio_client_free(struct audio_client *ac) { int loopcnt; struct audio_port_data *port; struct list_head *ptr, *next; struct asm_no_wait_node *node; if (!ac) { pr_err("%s: ac %p\n", __func__, ac); return; Loading @@ -922,6 +977,13 @@ void q6asm_audio_client_free(struct audio_client *ac) } } list_for_each_safe(ptr, next, &ac->no_wait_que) { node = list_entry(ptr, struct asm_no_wait_node, list); list_del(&node->list); kfree(node); } list_del(&ac->no_wait_que); apr_deregister(ac->apr2); ac->apr2 = NULL; apr_deregister(ac->apr); Loading Loading @@ -1060,6 +1122,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); INIT_LIST_HEAD(&ac->no_wait_que); atomic_set(&ac->mem_state, 0); rc = send_asm_custom_topology(ac); Loading Loading @@ -1435,29 +1498,18 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv) return 0; } static int32_t is_no_wait_cmd_rsp(uint32_t opcode, uint32_t *cmd_type) static bool remove_no_wait_cmd(struct audio_client *ac, uint32_t opcode, uint32_t *cmd_type) { if (opcode == APR_BASIC_RSP_RESULT) { if (cmd_type != NULL) { switch (cmd_type[0]) { case ASM_SESSION_CMD_RUN_V2: case ASM_SESSION_CMD_PAUSE: case ASM_DATA_CMD_EOS: case ASM_DATA_CMD_REMOVE_INITIAL_SILENCE: case ASM_DATA_CMD_REMOVE_TRAILING_SILENCE: case ASM_STREAM_CMD_SET_PP_PARAMS_V2: return 1; default: pr_debug("%s: default err 0x%x\n", __func__, cmd_type[0]); break; } return q6asm_remove_nowait_opcode(ac, cmd_type[0]); } else pr_err("%s: null pointer!", __func__); } else if (opcode == ASM_DATA_EVENT_RENDERED_EOS) return 1; return q6asm_remove_nowait_opcode(ac, ASM_DATA_CMD_EOS); return 0; return false; } static void q6asm_process_mtmx_get_param_rsp(struct audio_client *ac, Loading Loading @@ -1545,7 +1597,7 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) payload = data->payload; if ((atomic_read(&ac->nowait_cmd_cnt) > 0) && is_no_wait_cmd_rsp(data->opcode, payload)) { remove_no_wait_cmd(ac, data->opcode, payload)) { pr_debug("%s: nowait_cmd_cnt %d\n", __func__, atomic_read(&ac->nowait_cmd_cnt)); Loading Loading @@ -2837,9 +2889,11 @@ static int __q6asm_run_nowait(struct audio_client *ac, uint32_t flags, /* have to increase first avoid race */ atomic_inc(&ac->nowait_cmd_cnt); q6asm_add_nowait_opcode(ac, run.hdr.opcode); rc = apr_send_pkt(ac->apr, (uint32_t *) &run); if (rc < 0) { atomic_dec(&ac->nowait_cmd_cnt); q6asm_remove_nowait_opcode(ac, run.hdr.opcode); pr_err("%s: Commmand run failed[%d]", __func__, rc); return -EINVAL; } Loading Loading @@ -6265,9 +6319,11 @@ static int __q6asm_cmd_nowait(struct audio_client *ac, int cmd, hdr.opcode); /* have to increase first avoid race */ atomic_inc(&ac->nowait_cmd_cnt); q6asm_add_nowait_opcode(ac, hdr.opcode); rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr); if (rc < 0) { atomic_dec(&ac->nowait_cmd_cnt); q6asm_remove_nowait_opcode(ac, hdr.opcode); pr_err("%s: Commmand 0x%x failed %d\n", __func__, hdr.opcode, rc); goto fail_cmd; Loading Loading @@ -6323,10 +6379,12 @@ int __q6asm_send_meta_data(struct audio_client *ac, uint32_t stream_id, silence.num_samples_to_remove = initial_samples; atomic_inc(&ac->nowait_cmd_cnt); q6asm_add_nowait_opcode(ac, silence.hdr.opcode); rc = apr_send_pkt(ac->apr, (uint32_t *) &silence); if (rc < 0) { pr_err("%s: Commmand silence failed[%d]", __func__, rc); atomic_dec(&ac->nowait_cmd_cnt); q6asm_remove_nowait_opcode(ac, silence.hdr.opcode); goto fail_cmd; } Loading @@ -6334,10 +6392,12 @@ int __q6asm_send_meta_data(struct audio_client *ac, uint32_t stream_id, silence.num_samples_to_remove = trailing_samples; atomic_inc(&ac->nowait_cmd_cnt); q6asm_add_nowait_opcode(ac, silence.hdr.opcode); rc = apr_send_pkt(ac->apr, (uint32_t *) &silence); if (rc < 0) { pr_err("%s: Commmand silence failed[%d]", __func__, rc); atomic_dec(&ac->nowait_cmd_cnt); q6asm_remove_nowait_opcode(ac, silence.hdr.opcode); goto fail_cmd; } Loading Loading @@ -6837,10 +6897,12 @@ static int q6asm_send_asm_cal_nowait(struct audio_client *ac) payload_params.data_payload_size); atomic_inc(&ac->nowait_cmd_cnt); q6asm_add_nowait_opcode(ac, hdr.opcode); rc = apr_send_pkt(ac->apr, (uint32_t *) asm_params); if (rc < 0) { pr_err("%s: audio audstrm cal send failed\n", __func__); atomic_dec(&ac->nowait_cmd_cnt); q6asm_remove_nowait_opcode(ac, hdr.opcode); rc = -EINVAL; goto done; } Loading Loading @@ -7060,6 +7122,7 @@ static int __init q6asm_init(void) } atomic_set(&common_client.cmd_state, 0); atomic_set(&common_client.nowait_cmd_cnt, 0); INIT_LIST_HEAD(&common_client.no_wait_que); atomic_set(&common_client.mem_state, 0); ret = q6asm_init_cal_data(); Loading