diff --git a/dsp/q6asm.c b/dsp/q6asm.c index 4f61fbec5df2..3bcf4f1cd05b 100644 --- a/dsp/q6asm.c +++ b/dsp/q6asm.c @@ -2005,10 +2005,10 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) break; } case ASM_STREAM_CMD_GET_PP_PARAMS_V2: - pr_debug("%s: ASM_STREAM_CMD_GET_PP_PARAMS_V2 session %d opcode 0x%x token 0x%x src %d dest %d\n", - __func__, ac->session, - data->opcode, data->token, - data->src_port, data->dest_port); + case ASM_STREAM_CMD_GET_PP_PARAMS_V3: + pr_debug("%s: ASM_STREAM_CMD_GET_PP_PARAMS session %d opcode 0x%x token 0x%x src %d dest %d\n", + __func__, ac->session, data->opcode, + data->token, data->src_port, data->dest_port); /* Should only come here if there is an APR */ /* error or malformed APR packet. Otherwise */ /* response will be returned as */ @@ -2085,13 +2085,13 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) break; } case ASM_STREAM_CMDRSP_GET_PP_PARAMS_V2: - pr_debug("%s: ASM_STREAM_CMDRSP_GET_PP_PARAMS_V2 session %d opcode 0x%x token 0x%x src %d dest %d\n", - __func__, ac->session, data->opcode, - data->token, - data->src_port, data->dest_port); + case ASM_STREAM_CMDRSP_GET_PP_PARAMS_V3: + pr_debug("%s: ASM_STREAM_CMDRSP_GET_PP_PARAMS session %d opcode 0x%x token 0x%x src %d dest %d\n", + __func__, ac->session, data->opcode, data->token, + data->src_port, data->dest_port); if (payload[0] != 0) { - pr_err("%s: ASM_STREAM_CMDRSP_GET_PP_PARAMS_V2 returned error = 0x%x\n", - __func__, payload[0]); + pr_err("%s: ASM_STREAM_CMDRSP_GET_PP_PARAMS returned error = 0x%x\n", + __func__, payload[0]); } else if (generic_get_data) { generic_get_data->valid = 1; if (generic_get_data->is_inband) { diff --git a/dsp/q6voice.c b/dsp/q6voice.c index 801e76168541..788805e0bdf5 100644 --- a/dsp/q6voice.c +++ b/dsp/q6voice.c @@ -7456,6 +7456,7 @@ static int32_t qdsp_cvs_callback(struct apr_client_data *data, void *priv) data->payload_size); break; case VSS_ICOMMON_CMD_GET_PARAM_V2: + case VSS_ICOMMON_CMD_GET_PARAM_V3: pr_debug("%s: VSS_ICOMMON_CMD_GET_PARAM_V2\n", __func__); /* Should only come here if there is an APR */ @@ -7589,7 +7590,8 @@ static int32_t qdsp_cvs_callback(struct apr_client_data *data, void *priv) pr_debug("Recd VSS_ISTREAM_EVT_NOT_READY\n"); } else if (data->opcode == VSS_ISTREAM_EVT_READY) { pr_debug("Recd VSS_ISTREAM_EVT_READY\n"); - } else if (data->opcode == VSS_ICOMMON_RSP_GET_PARAM) { + } else if (data->opcode == VSS_ICOMMON_RSP_GET_PARAM || + VSS_ICOMMON_RSP_GET_PARAM_V3) { pr_debug("%s: VSS_ICOMMON_RSP_GET_PARAM\n", __func__); ptr = data->payload; if (ptr[0] != 0) { @@ -7747,12 +7749,13 @@ static int32_t qdsp_cvp_callback(struct apr_client_data *data, void *priv) data->payload_size); break; default: - pr_debug("%s: invalid token for command VSS_ICOMMON_CMD_SET_PARAM_V2: %d\n", + pr_debug("%s: invalid token for command VSS_ICOMMON_CMD_SET_PARAM: %d\n", __func__, data->token); break; } break; case VSS_ICOMMON_CMD_GET_PARAM_V2: + case VSS_ICOMMON_CMD_GET_PARAM_V3: pr_debug("%s: VSS_ICOMMON_CMD_GET_PARAM_V2\n", __func__); /* Should only come here if there is an APR */ @@ -7819,7 +7822,8 @@ static int32_t qdsp_cvp_callback(struct apr_client_data *data, void *priv) break; } } - } else if (data->opcode == VSS_ICOMMON_RSP_GET_PARAM) { + } else if (data->opcode == VSS_ICOMMON_RSP_GET_PARAM || + VSS_ICOMMON_RSP_GET_PARAM_V3) { pr_debug("%s: VSS_ICOMMON_RSP_GET_PARAM\n", __func__); ptr = data->payload; if (ptr[0] != 0) { diff --git a/dsp/rtac.c b/dsp/rtac.c index 8f0db893d379..d23363597ea6 100644 --- a/dsp/rtac.c +++ b/dsp/rtac.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "adsp_err.h" @@ -103,14 +104,10 @@ struct rtac_afe_user_data { uint32_t cmd_size; uint32_t port_id; union { - struct rtac_afe_set { - struct afe_rtac_set_param_v2 cmd; - struct param_hdr_v1 data; - } rtac_afe_set; - struct rtac_afe_get { - struct afe_rtac_get_param_v2 cmd; - struct param_hdr_v1 data; - } rtac_afe_get; + struct afe_rtac_user_data_set_v2 v2_set; + struct afe_rtac_user_data_set_v3 v3_set; + struct afe_rtac_user_data_get_v2 v2_get; + struct afe_rtac_user_data_get_v3 v3_get; }; } __packed; @@ -804,7 +801,9 @@ int send_adm_apr(void *buf, u32 opcode) goto err; } - if (opcode == ADM_CMD_SET_PP_PARAMS_V5) { + switch (opcode) { + case ADM_CMD_SET_PP_PARAMS_V5: + case ADM_CMD_SET_PP_PARAMS_V6: /* set payload size to in-band payload */ /* set data size to actual out of band payload size */ data_size = payload_size - 4 * sizeof(u32); @@ -822,12 +821,15 @@ int send_adm_apr(void *buf, u32 opcode) buf + 7 * sizeof(u32), data_size)) { pr_err("%s: Could not copy payload from user buffer\n", __func__); - result = -EINVAL; + result = -EFAULT; goto err; } + /* set payload size in packet */ rtac_adm_buffer[8] = data_size; - } else { + break; + case ADM_CMD_GET_PP_PARAMS_V5: + case ADM_CMD_GET_PP_PARAMS_V6: if (payload_size > MAX_PAYLOAD_SIZE) { pr_err("%s: Invalid payload size = %d\n", __func__, payload_size); @@ -841,9 +843,14 @@ int send_adm_apr(void *buf, u32 opcode) buf + 3 * sizeof(u32), payload_size)) { pr_err("%s: Could not copy payload from user buffer\n", __func__); - result = -EINVAL; + result = -EFAULT; goto err; } + break; + default: + pr_err("%s: Invalid opcode %d\n", __func__, opcode); + result = -EINVAL; + goto err; } /* Pack header */ @@ -904,33 +911,39 @@ int send_adm_apr(void *buf, u32 opcode) if (opcode == ADM_CMD_GET_PP_PARAMS_V5) { bytes_returned = ((u32 *)rtac_cal[ADM_RTAC_CAL].cal_data. kvaddr)[2] + 3 * sizeof(u32); - - if (bytes_returned > rtac_cal[ADM_RTAC_CAL]. - map_data.map_size) { - pr_err("%s: Invalid data size = %d\n", - __func__, bytes_returned); - result = -EINVAL; - goto err; - } - - if (bytes_returned > user_buf_size) { - pr_err("%s: User buf not big enough, size = 0x%x, returned size = 0x%x\n", - __func__, user_buf_size, bytes_returned); - result = -EINVAL; - goto err; - } - - if (copy_to_user(buf, (void *) - rtac_cal[ADM_RTAC_CAL].cal_data.kvaddr, - bytes_returned)) { - pr_err("%s: Could not copy buffer to user,size = %d\n", - __func__, bytes_returned); - result = -EINVAL; - goto err; - } + } else if (opcode == ADM_CMD_GET_PP_PARAMS_V6) { + bytes_returned = + ((u32 *) rtac_cal[ADM_RTAC_CAL].cal_data.kvaddr)[3] + + 4 * sizeof(u32); } else { bytes_returned = data_size; + goto unlock; } + + if (bytes_returned > rtac_cal[ADM_RTAC_CAL].map_data.map_size) { + pr_err("%s: Invalid data size = %d\n", __func__, + bytes_returned); + result = -EINVAL; + goto err; + } + + if (bytes_returned > user_buf_size) { + pr_err("%s: User buf not big enough, size = 0x%x, returned size = 0x%x\n", + __func__, user_buf_size, bytes_returned); + result = -EINVAL; + goto err; + } + + if (copy_to_user((void __user *) buf, + rtac_cal[ADM_RTAC_CAL].cal_data.kvaddr, + bytes_returned)) { + pr_err("%s: Could not copy buffer to user,size = %d\n", + __func__, bytes_returned); + result = -EFAULT; + goto err; + } + +unlock: mutex_unlock(&rtac_adm_apr_mutex); done: return bytes_returned; @@ -1032,7 +1045,9 @@ int send_rtac_asm_apr(void *buf, u32 opcode) goto err; } - if (opcode == ASM_STREAM_CMD_SET_PP_PARAMS_V2) { + switch (opcode) { + case ASM_STREAM_CMD_SET_PP_PARAMS_V2: + case ASM_STREAM_CMD_SET_PP_PARAMS_V3: /* set payload size to in-band payload */ /* set data size to actual out of band payload size */ data_size = payload_size - 4 * sizeof(u32); @@ -1050,13 +1065,14 @@ int send_rtac_asm_apr(void *buf, u32 opcode) buf + 7 * sizeof(u32), data_size)) { pr_err("%s: Could not copy payload from user buffer\n", __func__); - result = -EINVAL; + result = -EFAULT; goto err; } /* set payload size in packet */ rtac_asm_buffer[8] = data_size; - - } else { + break; + case ASM_STREAM_CMD_GET_PP_PARAMS_V2: + case ASM_STREAM_CMD_GET_PP_PARAMS_V3: if (payload_size > MAX_PAYLOAD_SIZE) { pr_err("%s: Invalid payload size = %d\n", __func__, payload_size); @@ -1070,9 +1086,15 @@ int send_rtac_asm_apr(void *buf, u32 opcode) buf + 3 * sizeof(u32), payload_size)) { pr_err("%s: Could not copy payload from user buffer\n", __func__); - result = -EINVAL; + result = -EFAULT; goto err; } + + break; + default: + pr_err("%s: Invalid opcode %d\n", __func__, opcode); + result = -EINVAL; + goto err; } /* Pack header */ @@ -1135,33 +1157,39 @@ int send_rtac_asm_apr(void *buf, u32 opcode) if (opcode == ASM_STREAM_CMD_GET_PP_PARAMS_V2) { bytes_returned = ((u32 *)rtac_cal[ASM_RTAC_CAL].cal_data. kvaddr)[2] + 3 * sizeof(u32); - - if (bytes_returned > rtac_cal[ASM_RTAC_CAL]. - map_data.map_size) { - pr_err("%s: Invalid data size = %d\n", - __func__, bytes_returned); - result = -EINVAL; - goto err; - } - - if (bytes_returned > user_buf_size) { - pr_err("%s: User buf not big enough, size = 0x%x, returned size = 0x%x\n", - __func__, user_buf_size, bytes_returned); - result = -EINVAL; - goto err; - } - - if (copy_to_user(buf, (void *) - rtac_cal[ASM_RTAC_CAL].cal_data.kvaddr, - bytes_returned)) { - pr_err("%s: Could not copy buffer to user,size = %d\n", - __func__, bytes_returned); - result = -EINVAL; - goto err; - } + } else if (opcode == ASM_STREAM_CMD_GET_PP_PARAMS_V3) { + bytes_returned = + ((u32 *) rtac_cal[ASM_RTAC_CAL].cal_data.kvaddr)[3] + + 4 * sizeof(u32); } else { bytes_returned = data_size; + goto unlock; } + + if (bytes_returned > rtac_cal[ASM_RTAC_CAL].map_data.map_size) { + pr_err("%s: Invalid data size = %d\n", __func__, + bytes_returned); + result = -EINVAL; + goto err; + } + + if (bytes_returned > user_buf_size) { + pr_err("%s: User buf not big enough, size = 0x%x, returned size = 0x%x\n", + __func__, user_buf_size, bytes_returned); + result = -EINVAL; + goto err; + } + + if (copy_to_user((void __user *) buf, + rtac_cal[ASM_RTAC_CAL].cal_data.kvaddr, + bytes_returned)) { + pr_err("%s: Could not copy buffer to user,size = %d\n", + __func__, bytes_returned); + result = -EFAULT; + goto err; + } + +unlock: mutex_unlock(&rtac_asm_apr_mutex); done: return bytes_returned; @@ -1218,13 +1246,18 @@ static int fill_afe_apr_hdr(struct apr_hdr *apr_hdr, uint32_t port, return 0; } -static int send_rtac_afe_apr(void *buf, uint32_t opcode) +static int send_rtac_afe_apr(void __user *buf, uint32_t opcode) { int32_t result; uint32_t bytes_returned = 0; + uint32_t payload_size = 0; uint32_t port_index = 0; + uint32_t *afe_cmd = NULL; uint32_t apr_msg_size = 0; struct rtac_afe_user_data user_afe_buf; + struct mem_mapping_hdr *mem_hdr = NULL; + struct param_hdr_v1 *get_resp_v2; + struct param_hdr_v3 *get_resp_v3; pr_debug("%s\n", __func__); @@ -1272,95 +1305,126 @@ static int send_rtac_afe_apr(void *buf, uint32_t opcode) result = -EINVAL; goto err; } - if (opcode == AFE_PORT_CMD_SET_PARAM_V2) { - struct afe_rtac_set_param_v2 *afe_set_apr_msg; - /* set data size to actual out of band payload size */ - if (user_afe_buf.rtac_afe_set.cmd.payload_size > - rtac_cal[AFE_RTAC_CAL].map_data.map_size) { - pr_err("%s: Invalid data size = %d\n", - __func__, - user_afe_buf.rtac_afe_set.cmd.payload_size); + afe_cmd = + (u32 *) rtac_afe_buffer + sizeof(struct apr_hdr) / sizeof(u32); + + switch (opcode) { + case AFE_PORT_CMD_SET_PARAM_V2: + apr_msg_size = sizeof(struct afe_port_cmd_set_param_v2); + payload_size = user_afe_buf.v2_set.payload_size; + if (payload_size > rtac_cal[AFE_RTAC_CAL].map_data.map_size) { + pr_err("%s: Invalid payload size = %d\n", __func__, + payload_size); result = -EINVAL; goto err; } - /* Copy buffer to out-of-band payload */ - if (copy_from_user( - (void *) rtac_cal[AFE_RTAC_CAL].cal_data.kvaddr, - (void __user *) buf + - offsetof(struct rtac_afe_user_data, - rtac_afe_set.data), - user_afe_buf.rtac_afe_set.cmd.payload_size)) { - pr_err("%s: Could not copy payload from user buffer\n", - __func__); - result = -EINVAL; - goto err; - } + /* Copy the command to the rtac buffer */ + memcpy(afe_cmd, &user_afe_buf.v2_set, + sizeof(user_afe_buf.v2_set)); - /* Copy AFE APR Message */ - afe_set_apr_msg = (struct afe_rtac_set_param_v2 - *) ((u8 *) rtac_afe_buffer + - sizeof(struct apr_hdr)); - if (copy_from_user((void *) afe_set_apr_msg, + /* Copy the param data to the out-of-band location */ + if (copy_from_user(rtac_cal[AFE_RTAC_CAL].cal_data.kvaddr, (void __user *) buf + offsetof(struct rtac_afe_user_data, - rtac_afe_set.cmd), - sizeof(struct afe_rtac_set_param_v2))) { + v2_set.param_hdr), + payload_size)) { pr_err("%s: Could not copy payload from user buffer\n", __func__); + result = -EFAULT; + goto err; + } + break; + case AFE_PORT_CMD_SET_PARAM_V3: + apr_msg_size = sizeof(struct afe_port_cmd_set_param_v3); + payload_size = user_afe_buf.v3_set.payload_size; + if (payload_size > rtac_cal[AFE_RTAC_CAL].map_data.map_size) { + pr_err("%s: Invalid payload size = %d\n", __func__, + payload_size); result = -EINVAL; goto err; } - afe_set_apr_msg->payload_address_lsw = - lower_32_bits(rtac_cal[AFE_RTAC_CAL].cal_data.paddr); - afe_set_apr_msg->payload_address_msw = - msm_audio_populate_upper_32_bits( - rtac_cal[AFE_RTAC_CAL].cal_data.paddr); - afe_set_apr_msg->mem_map_handle = - rtac_cal[AFE_RTAC_CAL].map_data.map_handle; + /* Copy the command to the rtac buffer */ + memcpy(afe_cmd, &user_afe_buf.v3_set, + sizeof(user_afe_buf.v3_set)); - apr_msg_size = sizeof(struct apr_hdr) + - sizeof(struct afe_rtac_set_param_v2); - - } else { - struct afe_rtac_get_param_v2 *afe_get_apr_msg; + /* Copy the param data to the out-of-band location */ + if (copy_from_user(rtac_cal[AFE_RTAC_CAL].cal_data.kvaddr, + (void __user *) buf + + offsetof(struct rtac_afe_user_data, + v3_get.param_hdr), + payload_size)) { + pr_err("%s: Could not copy payload from user buffer\n", + __func__); + result = -EFAULT; + goto err; + } + break; + case AFE_PORT_CMD_GET_PARAM_V2: + apr_msg_size = sizeof(struct afe_port_cmd_get_param_v2); if (user_afe_buf.cmd_size > MAX_PAYLOAD_SIZE) { - pr_err("%s: Invalid payload size = %d\n", - __func__, user_afe_buf.cmd_size); + pr_err("%s: Invalid payload size = %d\n", __func__, + user_afe_buf.cmd_size); result = -EINVAL; goto err; } - /* Copy buffer to in-band payload */ - afe_get_apr_msg = (struct afe_rtac_get_param_v2 - *) ((u8 *) rtac_afe_buffer + - sizeof(struct apr_hdr)); - if (copy_from_user((void *) afe_get_apr_msg, + /* Copy the command and param data in-band */ + if (copy_from_user(afe_cmd, (void __user *) buf + offsetof(struct rtac_afe_user_data, - rtac_afe_get.cmd), - sizeof(struct afe_rtac_get_param_v2))) { + v2_get), + user_afe_buf.cmd_size)) { pr_err("%s: Could not copy payload from user buffer\n", - __func__); + __func__); + result = -EFAULT; + goto err; + } + break; + case AFE_PORT_CMD_GET_PARAM_V3: + apr_msg_size = sizeof(struct afe_port_cmd_get_param_v3); + + if (user_afe_buf.cmd_size > MAX_PAYLOAD_SIZE) { + pr_err("%s: Invalid payload size = %d\n", __func__, + user_afe_buf.cmd_size); result = -EINVAL; goto err; } - afe_get_apr_msg->payload_address_lsw = - lower_32_bits(rtac_cal[AFE_RTAC_CAL].cal_data.paddr); - afe_get_apr_msg->payload_address_msw = - msm_audio_populate_upper_32_bits( - rtac_cal[AFE_RTAC_CAL].cal_data.paddr); - afe_get_apr_msg->mem_map_handle = - rtac_cal[AFE_RTAC_CAL].map_data.map_handle; - afe_get_apr_msg->payload_size -= sizeof(struct apr_hdr); - apr_msg_size = sizeof(struct apr_hdr) + - sizeof(struct afe_rtac_get_param_v2); + /* Copy the command and param data in-band */ + if (copy_from_user(afe_cmd, + (void __user *) buf + + offsetof(struct rtac_afe_user_data, + v3_get), + user_afe_buf.cmd_size)) { + pr_err("%s: Could not copy payload from user buffer\n", + __func__); + result = -EFAULT; + goto err; + } + break; + default: + pr_err("%s: Invalid opcode %d\n", __func__, opcode); + result = -EINVAL; + goto err; } + /* + * The memory header is in the same location in all commands. Therefore, + * it doesn't matter what command the buffer is cast into. + */ + mem_hdr = &((struct afe_port_cmd_set_param_v3 *) rtac_afe_buffer) + ->mem_hdr; + mem_hdr->data_payload_addr_lsw = + lower_32_bits(rtac_cal[AFE_RTAC_CAL].cal_data.paddr); + mem_hdr->data_payload_addr_msw = msm_audio_populate_upper_32_bits( + rtac_cal[AFE_RTAC_CAL].cal_data.paddr); + mem_hdr->mem_map_handle = rtac_cal[AFE_RTAC_CAL].map_data.map_handle; + + /* Fill the APR header at the end so we have the correct message size */ fill_afe_apr_hdr((struct apr_hdr *) rtac_afe_buffer, port_index, opcode, apr_msg_size); @@ -1398,41 +1462,44 @@ static int send_rtac_afe_apr(void *buf, uint32_t opcode) } if (opcode == AFE_PORT_CMD_GET_PARAM_V2) { - struct param_hdr_v1 *get_resp; - - get_resp = (struct param_hdr_v1 *) rtac_cal[AFE_RTAC_CAL] - .cal_data.kvaddr; - + get_resp_v2 = (struct param_hdr_v1 *) rtac_cal[AFE_RTAC_CAL] + .cal_data.kvaddr; bytes_returned = - get_resp->param_size + sizeof(struct param_hdr_v1); - - if (bytes_returned > rtac_cal[AFE_RTAC_CAL]. - map_data.map_size) { - pr_err("%s: Invalid data size = %d\n", - __func__, bytes_returned); - result = -EINVAL; - goto err; - } - - if (bytes_returned > user_afe_buf.buf_size) { - pr_err("%s: user size = 0x%x, returned size = 0x%x\n", - __func__, user_afe_buf.buf_size, - bytes_returned); - result = -EINVAL; - goto err; - } - - if (copy_to_user(buf, (void *) - rtac_cal[AFE_RTAC_CAL].cal_data.kvaddr, - bytes_returned)) { - pr_err("%s: Could not copy buffer to user,size = %d\n", - __func__, bytes_returned); - result = -EINVAL; - goto err; - } + get_resp_v2->param_size + sizeof(struct param_hdr_v1); + } else if (opcode == AFE_PORT_CMD_GET_PARAM_V3) { + get_resp_v3 = (struct param_hdr_v3 *) rtac_cal[AFE_RTAC_CAL] + .cal_data.kvaddr; + bytes_returned = + get_resp_v3->param_size + sizeof(struct param_hdr_v3); } else { - bytes_returned = user_afe_buf.rtac_afe_set.cmd.payload_size; + bytes_returned = payload_size; + goto unlock; } + + if (bytes_returned > rtac_cal[AFE_RTAC_CAL].map_data.map_size) { + pr_err("%s: Invalid data size = %d\n", __func__, + bytes_returned); + result = -EINVAL; + goto err; + } + + if (bytes_returned > user_afe_buf.buf_size) { + pr_err("%s: user size = 0x%x, returned size = 0x%x\n", __func__, + user_afe_buf.buf_size, bytes_returned); + result = -EINVAL; + goto err; + } + + if (copy_to_user((void __user *) buf, + rtac_cal[AFE_RTAC_CAL].cal_data.kvaddr, + bytes_returned)) { + pr_err("%s: Could not copy buffer to user,size = %d\n", + __func__, bytes_returned); + result = -EFAULT; + goto err; + } + +unlock: mutex_unlock(&rtac_afe_apr_mutex); done: return bytes_returned; @@ -1535,7 +1602,9 @@ int send_voice_apr(u32 mode, void *buf, u32 opcode) goto err; } - if (opcode == VSS_ICOMMON_CMD_SET_PARAM_V2) { + switch (opcode) { + case VSS_ICOMMON_CMD_SET_PARAM_V2: + case VSS_ICOMMON_CMD_SET_PARAM_V3: /* set payload size to in-band payload */ /* set data size to actual out of band payload size */ data_size = payload_size - 4 * sizeof(u32); @@ -1553,12 +1622,16 @@ int send_voice_apr(u32 mode, void *buf, u32 opcode) buf + 7 * sizeof(u32), data_size)) { pr_err("%s: Could not copy payload from user buffer\n", __func__); - result = -EINVAL; + result = -EFAULT; goto err; } /* set payload size in packet */ rtac_voice_buffer[8] = data_size; - } else { + /* set token for set param case */ + voice_params.token = VOC_RTAC_SET_PARAM_TOKEN; + break; + case VSS_ICOMMON_CMD_GET_PARAM_V2: + case VSS_ICOMMON_CMD_GET_PARAM_V3: if (payload_size > MAX_PAYLOAD_SIZE) { pr_err("%s: Invalid payload size = %d\n", __func__, payload_size); @@ -1572,9 +1645,16 @@ int send_voice_apr(u32 mode, void *buf, u32 opcode) buf + 3 * sizeof(u32), payload_size)) { pr_err("%s: Could not copy payload from user buffer\n", __func__); - result = -EINVAL; + result = -EFAULT; goto err; } + /* set token for get param case */ + voice_params.token = 0; + break; + default: + pr_err("%s: Invalid opcode %d\n", __func__, opcode); + result = -EINVAL; + goto err; } /* Pack header */ @@ -1588,18 +1668,14 @@ int send_voice_apr(u32 mode, void *buf, u32 opcode) voice_params.dest_svc = 0; voice_params.dest_domain = APR_DOMAIN_MODEM; voice_params.dest_port = (u16)dest_port; - voice_params.token = (opcode == VSS_ICOMMON_CMD_SET_PARAM_V2) ? - VOC_RTAC_SET_PARAM_TOKEN : - 0; voice_params.opcode = opcode; /* fill for out-of-band */ rtac_voice_buffer[5] = rtac_cal[VOICE_RTAC_CAL].map_data.map_handle; rtac_voice_buffer[6] = lower_32_bits(rtac_cal[VOICE_RTAC_CAL].cal_data.paddr); - rtac_voice_buffer[7] = - msm_audio_populate_upper_32_bits( - rtac_cal[VOICE_RTAC_CAL].cal_data.paddr); + rtac_voice_buffer[7] = msm_audio_populate_upper_32_bits( + rtac_cal[VOICE_RTAC_CAL].cal_data.paddr); memcpy(rtac_voice_buffer, &voice_params, sizeof(voice_params)); atomic_set(&rtac_voice_apr_data[mode].cmd_state, 1); @@ -1638,33 +1714,39 @@ int send_voice_apr(u32 mode, void *buf, u32 opcode) if (opcode == VSS_ICOMMON_CMD_GET_PARAM_V2) { bytes_returned = ((u32 *)rtac_cal[VOICE_RTAC_CAL].cal_data. kvaddr)[2] + 3 * sizeof(u32); - - if (bytes_returned > rtac_cal[VOICE_RTAC_CAL]. - map_data.map_size) { - pr_err("%s: Invalid data size = %d\n", - __func__, bytes_returned); - result = -EINVAL; - goto err; - } - - if (bytes_returned > user_buf_size) { - pr_err("%s: User buf not big enough, size = 0x%x, returned size = 0x%x\n", - __func__, user_buf_size, bytes_returned); - result = -EINVAL; - goto err; - } - - if (copy_to_user(buf, (void *) - rtac_cal[VOICE_RTAC_CAL].cal_data.kvaddr, - bytes_returned)) { - pr_err("%s: Could not copy buffer to user, size = %d\n", - __func__, bytes_returned); - result = -EINVAL; - goto err; - } + } else if (opcode == VSS_ICOMMON_CMD_GET_PARAM_V3) { + bytes_returned = + ((u32 *) rtac_cal[VOICE_RTAC_CAL].cal_data.kvaddr)[3] + + 4 * sizeof(u32); } else { bytes_returned = data_size; + goto unlock; } + + if (bytes_returned > rtac_cal[VOICE_RTAC_CAL].map_data.map_size) { + pr_err("%s: Invalid data size = %d\n", __func__, + bytes_returned); + result = -EINVAL; + goto err; + } + + if (bytes_returned > user_buf_size) { + pr_err("%s: User buf not big enough, size = 0x%x, returned size = 0x%x\n", + __func__, user_buf_size, bytes_returned); + result = -EINVAL; + goto err; + } + + if (copy_to_user((void __user *) buf, + rtac_cal[VOICE_RTAC_CAL].cal_data.kvaddr, + bytes_returned)) { + pr_err("%s: Could not copy buffer to user, size = %d\n", + __func__, bytes_returned); + result = -EFAULT; + goto err; + } + +unlock: mutex_unlock(&rtac_voice_apr_mutex); done: return bytes_returned; @@ -1684,8 +1766,8 @@ void get_rtac_adm_data(struct rtac_adm *adm_data) static long rtac_ioctl_shared(struct file *f, unsigned int cmd, void *arg) { + u32 opcode; int result = 0; - if (!arg) { pr_err("%s: No data sent to driver!\n", __func__); result = -EFAULT; @@ -1721,42 +1803,64 @@ static long rtac_ioctl_shared(struct file *f, } case AUDIO_GET_RTAC_ADM_CAL: - result = send_adm_apr((void *)arg, ADM_CMD_GET_PP_PARAMS_V5); + opcode = q6common_is_instance_id_supported() ? + ADM_CMD_GET_PP_PARAMS_V6 : + ADM_CMD_GET_PP_PARAMS_V5; + result = send_adm_apr((void *) arg, opcode); break; case AUDIO_SET_RTAC_ADM_CAL: - result = send_adm_apr((void *)arg, ADM_CMD_SET_PP_PARAMS_V5); + opcode = q6common_is_instance_id_supported() ? + ADM_CMD_SET_PP_PARAMS_V6 : + ADM_CMD_SET_PP_PARAMS_V5; + result = send_adm_apr((void *) arg, opcode); break; case AUDIO_GET_RTAC_ASM_CAL: - result = send_rtac_asm_apr((void *)arg, - ASM_STREAM_CMD_GET_PP_PARAMS_V2); + opcode = q6common_is_instance_id_supported() ? + ASM_STREAM_CMD_GET_PP_PARAMS_V3 : + ASM_STREAM_CMD_GET_PP_PARAMS_V2; + result = send_rtac_asm_apr((void *) arg, opcode); break; case AUDIO_SET_RTAC_ASM_CAL: - result = send_rtac_asm_apr((void *)arg, - ASM_STREAM_CMD_SET_PP_PARAMS_V2); + opcode = q6common_is_instance_id_supported() ? + ASM_STREAM_CMD_SET_PP_PARAMS_V3 : + ASM_STREAM_CMD_SET_PP_PARAMS_V2; + result = send_rtac_asm_apr((void *) arg, opcode); break; case AUDIO_GET_RTAC_CVS_CAL: - result = send_voice_apr(RTAC_CVS, (void *) arg, - VSS_ICOMMON_CMD_GET_PARAM_V2); + opcode = q6common_is_instance_id_supported() ? + VSS_ICOMMON_CMD_GET_PARAM_V3 : + VSS_ICOMMON_CMD_GET_PARAM_V2; + result = send_voice_apr(RTAC_CVS, (void *) arg, opcode); break; case AUDIO_SET_RTAC_CVS_CAL: - result = send_voice_apr(RTAC_CVS, (void *) arg, - VSS_ICOMMON_CMD_SET_PARAM_V2); + opcode = q6common_is_instance_id_supported() ? + VSS_ICOMMON_CMD_SET_PARAM_V3 : + VSS_ICOMMON_CMD_SET_PARAM_V2; + result = send_voice_apr(RTAC_CVS, (void *) arg, opcode); break; case AUDIO_GET_RTAC_CVP_CAL: - result = send_voice_apr(RTAC_CVP, (void *) arg, - VSS_ICOMMON_CMD_GET_PARAM_V2); + opcode = q6common_is_instance_id_supported() ? + VSS_ICOMMON_CMD_GET_PARAM_V3 : + VSS_ICOMMON_CMD_GET_PARAM_V2; + result = send_voice_apr(RTAC_CVP, (void *) arg, opcode); break; case AUDIO_SET_RTAC_CVP_CAL: - result = send_voice_apr(RTAC_CVP, (void *) arg, - VSS_ICOMMON_CMD_SET_PARAM_V2); + opcode = q6common_is_instance_id_supported() ? + VSS_ICOMMON_CMD_SET_PARAM_V3 : + VSS_ICOMMON_CMD_SET_PARAM_V2; + result = send_voice_apr(RTAC_CVP, (void *) arg, opcode); break; case AUDIO_GET_RTAC_AFE_CAL: - result = send_rtac_afe_apr((void *)arg, - AFE_PORT_CMD_GET_PARAM_V2); + opcode = q6common_is_instance_id_supported() ? + AFE_PORT_CMD_GET_PARAM_V3 : + AFE_PORT_CMD_GET_PARAM_V2; + result = send_rtac_afe_apr((void __user *) arg, opcode); break; case AUDIO_SET_RTAC_AFE_CAL: - result = send_rtac_afe_apr((void *)arg, - AFE_PORT_CMD_SET_PARAM_V2); + opcode = q6common_is_instance_id_supported() ? + AFE_PORT_CMD_SET_PARAM_V3 : + AFE_PORT_CMD_SET_PARAM_V2; + result = send_rtac_afe_apr((void __user *) arg, opcode); break; default: pr_err("%s: Invalid IOCTL, command = %d!\n", diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h index cbbed10df8f5..d068e683ff75 100644 --- a/include/dsp/apr_audio-v2.h +++ b/include/dsp/apr_audio-v2.h @@ -498,6 +498,7 @@ struct adm_cmd_device_open_v6 { /* Sets one or more parameters to a COPP. */ #define ADM_CMD_SET_PP_PARAMS_V5 0x00010328 +#define ADM_CMD_SET_PP_PARAMS_V6 0x0001035D /* Payload of the #ADM_CMD_SET_PP_PARAMS_V5 command. * If the data_payload_addr_lsw and data_payload_addr_msw element @@ -639,6 +640,7 @@ struct adm_cmd_rsp_device_open_v5 { /* This command allows a query of one COPP parameter. */ #define ADM_CMD_GET_PP_PARAMS_V5 0x0001032A +#define ADM_CMD_GET_PP_PARAMS_V6 0x0001035E /* Payload an #ADM_CMD_GET_PP_PARAMS_V5 command. */ struct adm_cmd_get_pp_params_v5 { @@ -1534,46 +1536,79 @@ struct afe_sidetone_iir_filter_config_params { #define AFE_PARAM_ID_LOOPBACK_GAIN_PER_PATH 0x00010206 /* Used by RTAC */ -struct afe_rtac_set_param_v2 { +struct afe_rtac_user_data_set_v2 { + /* Port interface and direction (Rx or Tx) to start. */ u16 port_id; -/* Port interface and direction (Rx or Tx) to start. */ + /* Actual size of the payload in bytes. + * This is used for parsing the parameter payload. + * Supported values: > 0 + */ u16 payload_size; -/* Actual size of the payload in bytes. - * This is used for parsing the parameter payload. - * Supported values: > 0 - */ -u32 payload_address_lsw; -/* LSW of 64 bit Payload address. - * Address should be 32-byte, - * 4kbyte aligned and must be contiguous memory. - */ + /* The header detailing the memory mapping for out of band. */ + struct mem_mapping_hdr mem_hdr; -u32 payload_address_msw; -/* MSW of 64 bit Payload address. - * In case of 32-bit shared memory address, - * this field must be set to zero. - * In case of 36-bit shared memory address, - * bit-4 to bit-31 must be set to zero. - * Address should be 32-byte, 4kbyte aligned - * and must be contiguous memory. - */ + /* The parameter header for the parameter data to set */ + struct param_hdr_v1 param_hdr; -u32 mem_map_handle; -/* Memory map handle returned by - * AFE_SERVICE_CMD_SHARED_MEM_MAP_REGIONS commands. - * Supported Values: - * - NULL -- Message. The parameter data is in-band. - * - Non-NULL -- The parameter data is Out-band.Pointer to - * the physical address - * in shared memory of the payload data. - * An optional field is available if parameter - * data is in-band: - * afe_param_data_v2 param_data[...]. - * For detailed payload content, see the - * afe_port_param_data_v2 structure. - */ + /* The parameter data to be filled when sent inband */ + u32 *param_data; +} __packed; + +struct afe_rtac_user_data_set_v3 { + /* Port interface and direction (Rx or Tx) to start. */ + u16 port_id; + /* Reserved for future enhancements. Must be 0. */ + u16 reserved; + + /* The header detailing the memory mapping for out of band. */ + struct mem_mapping_hdr mem_hdr; + + /* The size of the parameter header and parameter data */ + u32 payload_size; + + /* The parameter header for the parameter data to set */ + struct param_hdr_v3 param_hdr; + + /* The parameter data to be filled when sent inband */ + u32 *param_data; +} __packed; + +struct afe_rtac_user_data_get_v2 { + /* Port interface and direction (Rx or Tx) to start. */ + u16 port_id; + + /* Actual size of the payload in bytes. + * This is used for parsing the parameter payload. + * Supported values: > 0 + */ + u16 payload_size; + + /* The header detailing the memory mapping for out of band. */ + struct mem_mapping_hdr mem_hdr; + + /* The module ID of the parameter to get */ + u32 module_id; + + /* The parameter ID of the parameter to get */ + u32 param_id; + + /* The parameter data to be filled when sent inband */ + struct param_hdr_v1 param_hdr; +} __packed; + +struct afe_rtac_user_data_get_v3 { + /* Port interface and direction (Rx or Tx) to start. */ + u16 port_id; + /* Reserved for future enhancements. Must be 0. */ + u16 reserved; + + /* The header detailing the memory mapping for out of band. */ + struct mem_mapping_hdr mem_hdr; + + /* The parameter data to be filled when sent inband */ + struct param_hdr_v3 param_hdr; } __packed; #define AFE_PORT_CMD_SET_PARAM_V2 0x000100EF @@ -6571,6 +6606,7 @@ struct asm_stream_cmd_open_transcode_loopback_t { #define ASM_STREAM_CMD_FLUSH_READBUFS 0x00010C09 #define ASM_STREAM_CMD_SET_PP_PARAMS_V2 0x00010DA1 +#define ASM_STREAM_CMD_SET_PP_PARAMS_V3 0x0001320D struct asm_stream_cmd_set_pp_params_v2 { u32 data_payload_addr_lsw; @@ -6624,6 +6660,7 @@ struct asm_stream_param_data_v2 { } __packed; #define ASM_STREAM_CMD_GET_PP_PARAMS_V2 0x00010DA2 +#define ASM_STREAM_CMD_GET_PP_PARAMS_V3 0x0001320E struct asm_stream_cmd_get_pp_params_v2 { u32 data_payload_addr_lsw; @@ -6801,6 +6838,7 @@ struct asm_aac_dual_mono_mapping_param { } __packed; #define ASM_STREAM_CMDRSP_GET_PP_PARAMS_V2 0x00010DA4 +#define ASM_STREAM_CMDRSP_GET_PP_PARAMS_V3 0x0001320F struct asm_stream_cmdrsp_get_pp_params_v2 { u32 status;