int afe_loopback(u16 enable, u16 rx_port, u16 tx_port) { struct afe_loopback_cfg_v1 lb_cmd; int ret = 0; int index = 0; ret = afe_q6_interface_prepare(); if (ret != 0) return ret; index = q6audio_get_port_index(rx_port); if (q6audio_validate_port(rx_port) < 0) return -EINVAL; lb_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(20), APR_PKT_VER); lb_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(lb_cmd) - APR_HDR_SIZE); lb_cmd.hdr.src_port = 0; lb_cmd.hdr.dest_port = 0; lb_cmd.hdr.token = index; lb_cmd.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2; lb_cmd.param.port_id = tx_port; lb_cmd.param.payload_size = (sizeof(lb_cmd) - sizeof(struct apr_hdr) - sizeof(struct afe_port_cmd_set_param_v2)); lb_cmd.param.payload_address_lsw = 0x00; lb_cmd.param.payload_address_msw = 0x00; lb_cmd.param.mem_map_handle = 0x00; lb_cmd.pdata.module_id = AFE_MODULE_LOOPBACK; lb_cmd.pdata.param_id = AFE_PARAM_ID_LOOPBACK_CONFIG; lb_cmd.pdata.param_size = lb_cmd.param.payload_size - sizeof(struct afe_port_param_data_v2); lb_cmd.dst_port_id = rx_port; lb_cmd.routing_mode = LB_MODE_DEFAULT; lb_cmd.enable = (enable ? 1 : 0); lb_cmd.loopback_cfg_minor_version = AFE_API_VERSION_LOOPBACK_CONFIG; atomic_set(&this_afe.state, 1); ret = apr_send_pkt(this_afe.apr, (uint32_t *) &lb_cmd); if (ret < 0) { pr_err("%s: AFE loopback failed\n", __func__); ret = -EINVAL; goto done; } pr_debug("%s: waiting for this_afe.wait[%d]\n", __func__, index); ret = wait_event_timeout(this_afe.wait[index], (atomic_read(&this_afe.state) == 0), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); ret = -EINVAL; } done: return ret; }
int adm_memory_unmap_regions(int32_t port_id) { struct avs_cmd_shared_mem_unmap_regions unmap_regions; int ret = 0; int index = 0; pr_debug("%s\n", __func__); if (this_adm.apr == NULL) { pr_err("%s APR handle NULL\n", __func__); return -EINVAL; } port_id = q6audio_convert_virtual_to_portid(port_id); if (q6audio_validate_port(port_id) < 0) { pr_err("%s port idi[%d] is invalid\n", __func__, port_id); return -ENODEV; } index = q6audio_get_port_index(port_id); unmap_regions.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); unmap_regions.hdr.pkt_size = sizeof(unmap_regions); unmap_regions.hdr.src_port = 0; unmap_regions.hdr.dest_port = atomic_read(&this_adm.copp_id[index]); unmap_regions.hdr.token = port_id; unmap_regions.hdr.opcode = ADM_CMD_SHARED_MEM_UNMAP_REGIONS; unmap_regions.mem_map_handle = atomic_read(&this_adm. mem_map_cal_handles[atomic_read(&this_adm.mem_map_cal_index)]); atomic_set(&this_adm.copp_stat[index], 0); ret = apr_send_pkt(this_adm.apr, (uint32_t *) &unmap_regions); if (ret < 0) { pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__, unmap_regions.hdr.opcode, ret); ret = -EINVAL; goto fail_cmd; } ret = wait_event_timeout(this_adm.wait[index], atomic_read(&this_adm.copp_stat[index]), 5 * HZ); if (!ret) { pr_err("%s: timeout. waited for memory_unmap index %d\n", __func__, index); ret = -EINVAL; goto fail_cmd; } else { pr_debug("%s: Unmap handle 0x%x succeeded\n", __func__, unmap_regions.mem_map_handle); } fail_cmd: return ret; }
int afe_close(int port_id) { struct afe_port_cmd_device_stop stop; int ret = 0; int index = 0; if (this_afe.apr == NULL) { pr_err("AFE is already closed\n"); ret = -EINVAL; goto fail_cmd; } pr_debug("%s: port_id=%d\n", __func__, port_id); index = q6audio_get_port_index(port_id); if (q6audio_validate_port(port_id) < 0) return -EINVAL; port_id = q6audio_convert_virtual_to_portid(port_id); stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); stop.hdr.pkt_size = sizeof(stop); stop.hdr.src_port = 0; stop.hdr.dest_port = 0; stop.hdr.token = index; stop.hdr.opcode = AFE_PORT_CMD_DEVICE_STOP; stop.port_id = q6audio_get_port_id(port_id); stop.reserved = 0; atomic_set(&this_afe.state, 1); ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop); if (ret < 0) { pr_err("%s: AFE close failed\n", __func__); ret = -EINVAL; goto fail_cmd; } ret = wait_event_timeout(this_afe.wait[index], (atomic_read(&this_afe.state) == 0), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); ret = -EINVAL; goto fail_cmd; } fail_cmd: return ret; }
int afe_stop_pseudo_port(u16 port_id) { int ret = 0; struct afe_pseudoport_stop_command stop; int index = 0; pr_debug("%s: port_id=%d\n", __func__, port_id); if (this_afe.apr == NULL) { pr_err("%s: AFE is already closed\n", __func__); return -EINVAL; } index = q6audio_get_port_index(port_id); if (q6audio_validate_port(port_id) < 0) return -EINVAL; stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); stop.hdr.pkt_size = sizeof(stop); stop.hdr.src_port = 0; stop.hdr.dest_port = 0; stop.hdr.token = 0; stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP; stop.port_id = port_id; stop.reserved = 0; stop.hdr.token = index; atomic_set(&this_afe.state, 1); ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop); if (ret < 0) { pr_err("%s: AFE close failed %d\n", __func__, ret); return -EINVAL; } ret = wait_event_timeout(this_afe.wait[index], (atomic_read(&this_afe.state) == 0), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); return -EINVAL; } return 0; }
int afe_start_pseudo_port(u16 port_id) { int ret = 0; struct afe_pseudoport_start_command start; int index = 0; pr_debug("%s: port_id=%d\n", __func__, port_id); ret = afe_q6_interface_prepare(); if (ret != 0) return ret; index = q6audio_get_port_index(port_id); if (q6audio_validate_port(port_id) < 0) return -EINVAL; start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); start.hdr.pkt_size = sizeof(start); start.hdr.src_port = 0; start.hdr.dest_port = 0; start.hdr.token = 0; start.hdr.opcode = AFE_PSEUDOPORT_CMD_START; start.port_id = port_id; start.timing = 1; start.hdr.token = index; atomic_set(&this_afe.state, 1); ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start); if (ret < 0) { pr_err("%s: AFE enable for port %d failed %d\n", __func__, port_id, ret); return -EINVAL; } ret = wait_event_timeout(this_afe.wait[index], (atomic_read(&this_afe.state) == 0), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); return -EINVAL; } return 0; }
int q6audio_convert_virtual_to_portid(u16 port_id) { int ret; /* if port_id is virtual, convert to physical.. * if port_id is already physical, return physical */ if (q6audio_validate_port(port_id) < 0) { if (port_id == RT_PROXY_DAI_001_RX || port_id == RT_PROXY_DAI_001_TX || port_id == RT_PROXY_DAI_002_RX || port_id == RT_PROXY_DAI_002_TX) ret = VIRTUAL_ID_TO_PORTID(port_id); else ret = -EINVAL; } else ret = port_id; return ret; }
int adm_close(int port_id) { struct apr_hdr close; int ret = 0; int index = 0; port_id = q6audio_convert_virtual_to_portid(port_id); index = q6audio_get_port_index(port_id); if (q6audio_validate_port(port_id) < 0) return -EINVAL; pr_debug("%s port_id=%d index %d\n", __func__, port_id, index); if (!(atomic_read(&this_adm.copp_cnt[index]))) { pr_err("%s: copp count for port[%d]is 0\n", __func__, port_id); goto fail_cmd; } atomic_dec(&this_adm.copp_cnt[index]); if (!(atomic_read(&this_adm.copp_cnt[index]))) { close.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); close.pkt_size = sizeof(close); close.src_svc = APR_SVC_ADM; close.src_domain = APR_DOMAIN_APPS; close.src_port = port_id; close.dest_svc = APR_SVC_ADM; close.dest_domain = APR_DOMAIN_ADSP; close.dest_port = atomic_read(&this_adm.copp_id[index]); close.token = port_id; close.opcode = ADM_CMD_DEVICE_CLOSE_V5; atomic_set(&this_adm.copp_id[index], RESET_COPP_ID); atomic_set(&this_adm.copp_stat[index], 0); pr_debug("%s:coppid %d portid=%d index=%d coppcnt=%d\n", __func__, atomic_read(&this_adm.copp_id[index]), port_id, index, atomic_read(&this_adm.copp_cnt[index])); ret = apr_send_pkt(this_adm.apr, (uint32_t *)&close); if (ret < 0) { pr_err("%s ADM close failed\n", __func__); ret = -EINVAL; goto fail_cmd; } ret = wait_event_timeout(this_adm.wait[index], atomic_read(&this_adm.copp_stat[index]), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: ADM cmd Route failed for port %d\n", __func__, port_id); ret = -EINVAL; goto fail_cmd; } rtac_remove_adm_device(port_id); } fail_cmd: return ret; }
int adm_memory_map_regions(int port_id, uint32_t *buf_add, uint32_t mempool_id, uint32_t *bufsz, uint32_t bufcnt) { struct avs_cmd_shared_mem_map_regions *mmap_regions = NULL; struct avs_shared_map_region_payload *mregions = NULL; void *mmap_region_cmd = NULL; void *payload = NULL; int ret = 0; int i = 0; int cmd_size = 0; int index = 0; pr_debug("%s\n", __func__); if (this_adm.apr == NULL) { this_adm.apr = apr_register("ADSP", "ADM", adm_callback, 0xFFFFFFFF, &this_adm); if (this_adm.apr == NULL) { pr_err("%s: Unable to register ADM\n", __func__); ret = -ENODEV; return ret; } rtac_set_adm_handle(this_adm.apr); } port_id = q6audio_convert_virtual_to_portid(port_id); if (q6audio_validate_port(port_id) < 0) { pr_err("%s port id[%d] is invalid\n", __func__, port_id); return -ENODEV; } index = q6audio_get_port_index(port_id); cmd_size = sizeof(struct avs_cmd_shared_mem_map_regions) + sizeof(struct avs_shared_map_region_payload) * bufcnt; mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL); if (!mmap_region_cmd) { pr_err("%s: allocate mmap_region_cmd failed\n", __func__); return -ENOMEM; } mmap_regions = (struct avs_cmd_shared_mem_map_regions *)mmap_region_cmd; mmap_regions->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); mmap_regions->hdr.pkt_size = cmd_size; mmap_regions->hdr.src_port = 0; mmap_regions->hdr.dest_port = 0; mmap_regions->hdr.token = 0; mmap_regions->hdr.opcode = ADM_CMD_SHARED_MEM_MAP_REGIONS; mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL & 0x00ff; mmap_regions->num_regions = bufcnt & 0x00ff; mmap_regions->property_flag = 0x00; pr_debug("%s: map_regions->num_regions = %d\n", __func__, mmap_regions->num_regions); payload = ((u8 *) mmap_region_cmd + sizeof(struct avs_cmd_shared_mem_map_regions)); mregions = (struct avs_shared_map_region_payload *)payload; for (i = 0; i < bufcnt; i++) { mregions->shm_addr_lsw = buf_add[i]; mregions->shm_addr_msw = 0x00; mregions->mem_size_bytes = bufsz[i]; ++mregions; } atomic_set(&this_adm.copp_stat[0], 0); ret = apr_send_pkt(this_adm.apr, (uint32_t *) mmap_region_cmd); if (ret < 0) { pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__, mmap_regions->hdr.opcode, ret); ret = -EINVAL; goto fail_cmd; } ret = wait_event_timeout(this_adm.wait[index], atomic_read(&this_adm.copp_stat[0]), 5 * HZ); if (!ret) { pr_err("%s: timeout. waited for memory_map\n", __func__); ret = -EINVAL; goto fail_cmd; } fail_cmd: kfree(mmap_region_cmd); return ret; }
int adm_open(int port_id, int path, int rate, int channel_mode, int topology) { struct adm_cmd_device_open_v5 open; int ret = 0; int index; int tmp_port = q6audio_get_port_id(port_id); pr_debug("%s: port %d path:%d rate:%d mode:%d\n", __func__, port_id, path, rate, channel_mode); port_id = q6audio_convert_virtual_to_portid(port_id); if (q6audio_validate_port(port_id) < 0) { pr_err("%s port idi[%d] is invalid\n", __func__, port_id); return -ENODEV; } index = q6audio_get_port_index(port_id); pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index); if (this_adm.apr == NULL) { this_adm.apr = apr_register("ADSP", "ADM", adm_callback, 0xFFFFFFFF, &this_adm); if (this_adm.apr == NULL) { pr_err("%s: Unable to register ADM\n", __func__); ret = -ENODEV; return ret; } rtac_set_adm_handle(this_adm.apr); } /* Create a COPP if port id are not enabled */ if (atomic_read(&this_adm.copp_cnt[index]) == 0) { open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); open.hdr.pkt_size = sizeof(open); open.hdr.src_svc = APR_SVC_ADM; open.hdr.src_domain = APR_DOMAIN_APPS; open.hdr.src_port = tmp_port; open.hdr.dest_svc = APR_SVC_ADM; open.hdr.dest_domain = APR_DOMAIN_ADSP; open.hdr.dest_port = tmp_port; open.hdr.token = port_id; open.hdr.opcode = ADM_CMD_DEVICE_OPEN_V5; open.mode_of_operation = path; /* Reserved for future use, need to set this to 0 */ open.flags = 0x00; open.endpoint_id_1 = tmp_port; open.endpoint_id_2 = 0xFFFF; /* convert path to acdb path */ if (path == ADM_PATH_PLAYBACK) open.topology_id = get_adm_rx_topology(); else { open.topology_id = get_adm_tx_topology(); if ((open.topology_id == VPM_TX_SM_ECNS_COPP_TOPOLOGY) || (open.topology_id == VPM_TX_DM_FLUENCE_COPP_TOPOLOGY)) rate = 16000; } if (open.topology_id == 0) open.topology_id = topology; open.dev_num_channel = channel_mode & 0x00FF; open.bit_width = 16; open.sample_rate = rate; memset(open.dev_channel_mapping, 0, 8); if (channel_mode == 1) { open.dev_channel_mapping[0] = PCM_CHANNEL_FC; } else if (channel_mode == 2) { open.dev_channel_mapping[0] = PCM_CHANNEL_FL; open.dev_channel_mapping[1] = PCM_CHANNEL_FR; } else if (channel_mode == 6) { open.dev_channel_mapping[0] = PCM_CHANNEL_FL; open.dev_channel_mapping[1] = PCM_CHANNEL_FR; open.dev_channel_mapping[2] = PCM_CHANNEL_LFE; open.dev_channel_mapping[3] = PCM_CHANNEL_FC; open.dev_channel_mapping[4] = PCM_CHANNEL_LB; open.dev_channel_mapping[5] = PCM_CHANNEL_RB; } else { pr_err("%s invalid num_chan %d\n", __func__, channel_mode); return -EINVAL; } pr_debug("%s: port_id=%d rate=%d" "topology_id=0x%X\n", __func__, open.endpoint_id_1, \ open.sample_rate, open.topology_id); atomic_set(&this_adm.copp_stat[index], 0); ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open); if (ret < 0) { pr_err("%s:ADM enable for port %d for[%d] failed\n", __func__, tmp_port, port_id); ret = -EINVAL; goto fail_cmd; } /* Wait for the callback with copp id */ ret = wait_event_timeout(this_adm.wait[index], atomic_read(&this_adm.copp_stat[index]), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s ADM open failed for port %d" "for [%d]\n", __func__, tmp_port, port_id); ret = -EINVAL; goto fail_cmd; } } atomic_inc(&this_adm.copp_cnt[index]); return 0; fail_cmd: return ret; }
int adm_open(int port_id, int path, int rate, int channel_mode, int topology, bool perf_mode, uint16_t bits_per_sample) { struct adm_cmd_device_open_v5 open; int ret = 0; int index; int tmp_port = q6audio_get_port_id(port_id); pr_debug("%s: port %#x path:%d rate:%d mode:%d perf_mode:%d\n", __func__, port_id, path, rate, channel_mode, perf_mode); port_id = q6audio_convert_virtual_to_portid(port_id); if (q6audio_validate_port(port_id) < 0) { pr_err("%s port idi[%#x] is invalid\n", __func__, port_id); return -ENODEV; } index = q6audio_get_port_index(port_id); pr_debug("%s: Port ID %#x, index %d\n", __func__, port_id, index); if (this_adm.apr == NULL) { this_adm.apr = apr_register("ADSP", "ADM", adm_callback, 0xFFFFFFFF, &this_adm); if (this_adm.apr == NULL) { pr_err("%s: Unable to register ADM\n", __func__); ret = -ENODEV; return ret; } rtac_set_adm_handle(this_adm.apr); } if (!perf_mode) { atomic_set(&this_adm.copp_perf_mode[index], 0); send_adm_custom_topology(port_id); } else { atomic_set(&this_adm.copp_perf_mode[index], 1); } /* Create a COPP if port id are not enabled */ if ((!perf_mode && (atomic_read(&this_adm.copp_cnt[index]) == 0)) || (perf_mode && (atomic_read(&this_adm.copp_low_latency_cnt[index]) == 0))) { pr_debug("%s:opening ADM: perf_mode: %d\n", __func__, perf_mode); open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); open.hdr.pkt_size = sizeof(open); open.hdr.src_svc = APR_SVC_ADM; open.hdr.src_domain = APR_DOMAIN_APPS; open.hdr.src_port = tmp_port; open.hdr.dest_svc = APR_SVC_ADM; open.hdr.dest_domain = APR_DOMAIN_ADSP; open.hdr.dest_port = tmp_port; open.hdr.token = port_id; open.hdr.opcode = ADM_CMD_DEVICE_OPEN_V5; open.flags = 0x00; if (perf_mode) { open.flags |= ADM_LOW_LATENCY_DEVICE_SESSION << ADM_BIT_SHIFT_DEVICE_PERF_MODE_FLAG; } else { open.flags |= ADM_LEGACY_DEVICE_SESSION << ADM_BIT_SHIFT_DEVICE_PERF_MODE_FLAG; } open.mode_of_operation = path; open.endpoint_id_1 = tmp_port; if (this_adm.ec_ref_rx == -1) { open.endpoint_id_2 = 0xFFFF; } else if (this_adm.ec_ref_rx && (path != 1)) { open.endpoint_id_2 = this_adm.ec_ref_rx; this_adm.ec_ref_rx = -1; } open.topology_id = topology; if ((open.topology_id == VPM_TX_SM_ECNS_COPP_TOPOLOGY) || (open.topology_id == VPM_TX_DM_FLUENCE_COPP_TOPOLOGY)) rate = 16000; open.dev_num_channel = channel_mode & 0x00FF; open.bit_width = bits_per_sample; open.sample_rate = rate; memset(open.dev_channel_mapping, 0, 8); if (channel_mode == 1) { open.dev_channel_mapping[0] = PCM_CHANNEL_FC; } else if (channel_mode == 2) { open.dev_channel_mapping[0] = PCM_CHANNEL_FL; open.dev_channel_mapping[1] = PCM_CHANNEL_FR; } else if (channel_mode == 3) { open.dev_channel_mapping[0] = PCM_CHANNEL_FL; open.dev_channel_mapping[1] = PCM_CHANNEL_FR; open.dev_channel_mapping[2] = PCM_CHANNEL_FC; } else if (channel_mode == 4) { open.dev_channel_mapping[0] = PCM_CHANNEL_FL; open.dev_channel_mapping[1] = PCM_CHANNEL_FR; open.dev_channel_mapping[2] = PCM_CHANNEL_RB; open.dev_channel_mapping[3] = PCM_CHANNEL_LB; } else if (channel_mode == 5) { open.dev_channel_mapping[0] = PCM_CHANNEL_FL; open.dev_channel_mapping[1] = PCM_CHANNEL_FR; open.dev_channel_mapping[2] = PCM_CHANNEL_FC; open.dev_channel_mapping[3] = PCM_CHANNEL_LB; open.dev_channel_mapping[4] = PCM_CHANNEL_RB; } else if (channel_mode == 6) { open.dev_channel_mapping[0] = PCM_CHANNEL_FL; open.dev_channel_mapping[1] = PCM_CHANNEL_FR; open.dev_channel_mapping[2] = PCM_CHANNEL_FC; open.dev_channel_mapping[3] = PCM_CHANNEL_LFE; open.dev_channel_mapping[4] = PCM_CHANNEL_LB; open.dev_channel_mapping[5] = PCM_CHANNEL_RB; } else if (channel_mode == 8) { open.dev_channel_mapping[0] = PCM_CHANNEL_FL; open.dev_channel_mapping[1] = PCM_CHANNEL_FR; open.dev_channel_mapping[2] = PCM_CHANNEL_LFE; open.dev_channel_mapping[3] = PCM_CHANNEL_FC; open.dev_channel_mapping[4] = PCM_CHANNEL_LB; open.dev_channel_mapping[5] = PCM_CHANNEL_RB; open.dev_channel_mapping[6] = PCM_CHANNEL_RLC; open.dev_channel_mapping[7] = PCM_CHANNEL_RRC; } else { pr_err("%s invalid num_chan %d\n", __func__, channel_mode); return -EINVAL; } if ((open.dev_num_channel > 2) && multi_ch_map.set_channel_map) memcpy(open.dev_channel_mapping, multi_ch_map.channel_mapping, PCM_FORMAT_MAX_NUM_CHANNEL); pr_debug("%s: port_id=%#x rate=%d topology_id=0x%X\n", __func__, open.endpoint_id_1, open.sample_rate, open.topology_id); atomic_set(&this_adm.copp_stat[index], 0); ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open); if (ret < 0) { pr_err("%s:ADM enable for port %#x for[%d] failed\n", __func__, tmp_port, port_id); ret = -EINVAL; goto fail_cmd; } /* Wait for the callback with copp id */ ret = wait_event_timeout(this_adm.wait[index], atomic_read(&this_adm.copp_stat[index]), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s ADM open failed for port %#x for [%d]\n", __func__, tmp_port, port_id); ret = -EINVAL; goto fail_cmd; } } if (perf_mode) { atomic_inc(&this_adm.copp_low_latency_cnt[index]); pr_debug("%s: index: %d coppid: %d", __func__, index, atomic_read(&this_adm.copp_low_latency_id[index])); } else { atomic_inc(&this_adm.copp_cnt[index]); pr_debug("%s: index: %d coppid: %d", __func__, index, atomic_read(&this_adm.copp_id[index])); } return 0; fail_cmd: return ret; }
int afe_cmd_memory_map_nowait(int port_id, u32 dma_addr_p, u32 dma_buf_sz) { int ret = 0; int cmd_size = 0; void *payload = NULL; void *mmap_region_cmd = NULL; struct afe_service_cmd_shared_mem_map_regions *mregion = NULL; struct afe_service_shared_map_region_payload *mregion_pl = NULL; int index = 0; pr_debug("%s:\n", __func__); if (this_afe.apr == NULL) { this_afe.apr = apr_register("ADSP", "AFE", afe_callback, 0xFFFFFFFF, &this_afe); pr_debug("%s: Register AFE\n", __func__); if (this_afe.apr == NULL) { pr_err("%s: Unable to register AFE\n", __func__); ret = -ENODEV; return ret; } } index = q6audio_get_port_index(port_id); if (q6audio_validate_port(port_id) < 0) return -EINVAL; cmd_size = sizeof(struct afe_service_cmd_shared_mem_map_regions) + sizeof(struct afe_service_shared_map_region_payload); mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL); if (!mmap_region_cmd) { pr_err("%s: allocate mmap_region_cmd failed\n", __func__); return -ENOMEM; } mregion = (struct afe_service_cmd_shared_mem_map_regions *) mmap_region_cmd; mregion->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); mregion->hdr.pkt_size = sizeof(mregion); mregion->hdr.src_port = 0; mregion->hdr.dest_port = 0; mregion->hdr.token = 0; mregion->hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_MAP_REGIONS; mregion->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL; mregion->num_regions = 1; mregion->property_flag = 0x00; payload = ((u8 *) mmap_region_cmd + sizeof(struct afe_service_cmd_shared_mem_map_regions)); mregion_pl = (struct afe_service_shared_map_region_payload *)payload; mregion_pl->shm_addr_lsw = dma_addr_p; mregion_pl->shm_addr_msw = 0x00; mregion_pl->mem_size_bytes = dma_buf_sz; atomic_set(&this_afe.state, 1); ret = apr_send_pkt(this_afe.apr, (uint32_t *) mmap_region_cmd); if (ret < 0) { pr_err("%s: AFE memory map cmd failed %d\n", __func__, ret); ret = -EINVAL; return ret; } return 0; }
int afe_loopback_gain(u16 port_id, u16 volume) { struct afe_loopback_gain_per_path_param set_param; int ret = 0; int index = 0; if (this_afe.apr == NULL) { this_afe.apr = apr_register("ADSP", "AFE", afe_callback, 0xFFFFFFFF, &this_afe); pr_debug("%s: Register AFE\n", __func__); if (this_afe.apr == NULL) { pr_err("%s: Unable to register AFE\n", __func__); ret = -ENODEV; return ret; } } if (q6audio_validate_port(port_id) < 0) { pr_err("%s: Failed : Invalid Port id = %d\n", __func__, port_id); ret = -EINVAL; goto fail_cmd; } index = q6audio_get_port_index(port_id); if (q6audio_validate_port(port_id) < 0) return -EINVAL; /* RX ports numbers are even .TX ports numbers are odd. */ if (port_id % 2 == 0) { pr_err("%s: Failed : afe loopback gain only for TX ports. port_id %d\n", __func__, port_id); ret = -EINVAL; goto fail_cmd; } pr_debug("%s: %d %hX\n", __func__, port_id, volume); set_param.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); set_param.hdr.pkt_size = sizeof(set_param); set_param.hdr.src_port = 0; set_param.hdr.dest_port = 0; set_param.hdr.token = index; set_param.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2; set_param.param.port_id = port_id; set_param.param.payload_size = (sizeof(struct afe_loopback_gain_per_path_param) - sizeof(struct apr_hdr) - sizeof(struct afe_port_cmd_set_param_v2)); set_param.param.payload_address_lsw = 0; set_param.param.payload_address_msw = 0; set_param.param.mem_map_handle = 0; set_param.pdata.module_id = AFE_MODULE_LOOPBACK; set_param.pdata.param_id = AFE_PARAM_ID_LOOPBACK_GAIN_PER_PATH; set_param.pdata.param_size = (set_param.param.payload_size - sizeof(struct afe_port_param_data_v2)); set_param.rx_port_id = port_id; set_param.gain = volume; atomic_set(&this_afe.state, 1); ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_param); if (ret < 0) { pr_err("%s: AFE param set failed for port %d\n", __func__, port_id); ret = -EINVAL; goto fail_cmd; } ret = wait_event_timeout(this_afe.wait[index], (atomic_read(&this_afe.state) == 0), msecs_to_jiffies(TIMEOUT_MS)); if (ret < 0) { pr_err("%s: wait_event timeout\n", __func__); ret = -EINVAL; goto fail_cmd; } return 0; fail_cmd: return ret; }
int afe_open(u16 port_id, union afe_port_config *afe_config, int rate) { struct afe_port_cmd_device_start start; struct afe_audioif_config_command config; int ret = 0; int cfg_type; int index = 0; if (!afe_config) { pr_err("%s: Error, no configuration data\n", __func__); ret = -EINVAL; return ret; } pr_err("%s: %d %d\n", __func__, port_id, rate); index = q6audio_get_port_index(port_id); if (q6audio_validate_port(port_id) < 0) return -EINVAL; if ((port_id == RT_PROXY_DAI_001_RX) || (port_id == RT_PROXY_DAI_002_TX)) return -EINVAL; if ((port_id == RT_PROXY_DAI_002_RX) || (port_id == RT_PROXY_DAI_001_TX)) port_id = VIRTUAL_ID_TO_PORTID(port_id); ret = afe_q6_interface_prepare(); if (ret != 0) return ret; if (q6audio_validate_port(port_id) < 0) { pr_err("%s: Failed : Invalid Port id = %d\n", __func__, port_id); ret = -EINVAL; goto fail_cmd; } config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); config.hdr.pkt_size = sizeof(config); config.hdr.src_port = 0; config.hdr.dest_port = 0; config.hdr.token = index; switch (port_id) { case PRIMARY_I2S_RX: case PRIMARY_I2S_TX: cfg_type = AFE_PARAM_ID_I2S_CONFIG; break; case PCM_RX: case PCM_TX: cfg_type = AFE_PARAM_ID_PCM_CONFIG; break; case SECONDARY_I2S_RX: case SECONDARY_I2S_TX: case MI2S_RX: case MI2S_TX: cfg_type = AFE_PARAM_ID_I2S_CONFIG; break; case HDMI_RX: cfg_type = AFE_PARAM_ID_HDMI_CONFIG; break; case SLIMBUS_0_RX: case SLIMBUS_0_TX: case SLIMBUS_1_RX: case SLIMBUS_1_TX: case SLIMBUS_2_RX: case SLIMBUS_2_TX: case SLIMBUS_3_RX: case SLIMBUS_3_TX: case SLIMBUS_4_RX: case SLIMBUS_4_TX: cfg_type = AFE_PARAM_ID_SLIMBUS_CONFIG; break; default: pr_err("%s: Invalid port id 0x%x\n", __func__, port_id); ret = -EINVAL; goto fail_cmd; } config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2; config.param.port_id = q6audio_get_port_id(port_id); config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) - sizeof(config.param); config.param.payload_address_lsw = 0x00; config.param.payload_address_msw = 0x00; config.param.mem_map_handle = 0x00; config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE; config.pdata.param_id = cfg_type; config.pdata.param_size = sizeof(config.port); config.port = *afe_config; pr_debug("%s: param PL size=%d iparam_size[%d][%d %d %d %d] param_id[%x]\n", __func__, config.param.payload_size, config.pdata.param_size, sizeof(config), sizeof(config.param), sizeof(config.port), sizeof(struct apr_hdr), config.pdata.param_id); atomic_set(&this_afe.state, 1); atomic_set(&this_afe.status, 0); ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config); if (ret < 0) { pr_err("%s: AFE enable for port %d opcode[0x%x]failed\n", __func__, port_id, cfg_type); ret = -EINVAL; goto fail_cmd; } ret = wait_event_timeout(this_afe.wait[index], (atomic_read(&this_afe.state) == 0), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); ret = -EINVAL; goto fail_cmd; } if (atomic_read(&this_afe.status) != 0) { pr_err("%s: config cmd failed\n", __func__); ret = -EINVAL; goto fail_cmd; } start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); start.hdr.pkt_size = sizeof(start); start.hdr.src_port = 0; start.hdr.dest_port = 0; start.hdr.token = index; start.hdr.opcode = AFE_PORT_CMD_DEVICE_START; start.port_id = q6audio_get_port_id(port_id); pr_debug("%s: cmd device start opcode[0x%x] port id[0x%x]\n", __func__, start.hdr.opcode, start.port_id); atomic_set(&this_afe.state, 1); ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start); if (ret < 0) { pr_err("%s: AFE enable for port %d failed\n", __func__, port_id); ret = -EINVAL; goto fail_cmd; } ret = wait_event_timeout(this_afe.wait[index], (atomic_read(&this_afe.state) == 0), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); ret = -EINVAL; goto fail_cmd; } return 0; fail_cmd: return ret; }
int afe_sidetone(u16 tx_port_id, u16 rx_port_id, u16 enable, uint16_t gain) { struct afe_loopback_cfg_v1 cmd_sidetone; int ret = 0; int index = 0; pr_info("%s: tx_port_id:%d rx_port_id:%d enable:%d gain:%d\n", __func__, tx_port_id, rx_port_id, enable, gain); index = q6audio_get_port_index(rx_port_id); if (q6audio_validate_port(rx_port_id) < 0) return -EINVAL; cmd_sidetone.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cmd_sidetone.hdr.pkt_size = sizeof(cmd_sidetone); cmd_sidetone.hdr.src_port = 0; cmd_sidetone.hdr.dest_port = 0; cmd_sidetone.hdr.token = 0; cmd_sidetone.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2; /* should it be rx or tx port id ?? , bharath*/ cmd_sidetone.param.port_id = tx_port_id; /* size of data param & payload */ cmd_sidetone.param.payload_size = (sizeof(cmd_sidetone) - sizeof(struct apr_hdr) - sizeof(struct afe_port_cmd_set_param_v2)); cmd_sidetone.param.payload_address_lsw = 0x00; cmd_sidetone.param.payload_address_msw = 0x00; cmd_sidetone.param.mem_map_handle = 0x00; cmd_sidetone.pdata.module_id = AFE_MODULE_LOOPBACK; cmd_sidetone.pdata.param_id = AFE_PARAM_ID_LOOPBACK_CONFIG; /* size of actual payload only */ cmd_sidetone.pdata.param_size = cmd_sidetone.param.payload_size - sizeof(struct afe_port_param_data_v2); cmd_sidetone.loopback_cfg_minor_version = AFE_API_VERSION_LOOPBACK_CONFIG; cmd_sidetone.dst_port_id = rx_port_id; cmd_sidetone.routing_mode = LB_MODE_SIDETONE; cmd_sidetone.enable = enable; atomic_set(&this_afe.state, 1); ret = apr_send_pkt(this_afe.apr, (uint32_t *) &cmd_sidetone); if (ret < 0) { pr_err("%s: AFE sidetone failed for tx_port:%d rx_port:%d\n", __func__, tx_port_id, rx_port_id); ret = -EINVAL; goto fail_cmd; } ret = wait_event_timeout(this_afe.wait[index], (atomic_read(&this_afe.state) == 0), msecs_to_jiffies(TIMEOUT_MS)); if (ret < 0) { pr_err("%s: wait_event timeout\n", __func__); ret = -EINVAL; goto fail_cmd; } return 0; fail_cmd: return ret; }
static ssize_t afe_debug_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) { char *lb_str = filp->private_data; char lbuf[32]; int rc; unsigned long param[5]; if (cnt > sizeof(lbuf) - 1) return -EINVAL; rc = copy_from_user(lbuf, ubuf, cnt); if (rc) return -EFAULT; lbuf[cnt] = '\0'; if (!strncmp(lb_str, "afe_loopback", 12)) { rc = afe_get_parameters(lbuf, param, 3); if (!rc) { pr_info("%s %lu %lu %lu\n", lb_str, param[0], param[1], param[2]); if ((param[0] != AFE_LOOPBACK_ON) && (param[0] != AFE_LOOPBACK_OFF)) { pr_err("%s: Error, parameter 0 incorrect\n", __func__); rc = -EINVAL; goto afe_error; } if ((q6audio_validate_port(param[1]) < 0) || (q6audio_validate_port(param[2])) < 0) { pr_err("%s: Error, invalid afe port\n", __func__); } if (this_afe.apr == NULL) { pr_err("%s: Error, AFE not opened\n", __func__); rc = -EINVAL; } else { rc = afe_loopback(param[0], param[1], param[2]); } } else { pr_err("%s: Error, invalid parameters\n", __func__); rc = -EINVAL; } } else if (!strncmp(lb_str, "afe_loopback_gain", 17)) { rc = afe_get_parameters(lbuf, param, 2); if (!rc) { pr_info("%s %lu %lu\n", lb_str, param[0], param[1]); if (q6audio_validate_port(param[0]) < 0) { pr_err("%s: Error, invalid afe port\n", __func__); rc = -EINVAL; goto afe_error; } if (param[1] < 0 || param[1] > 100) { pr_err("%s: Error, volume shoud be 0 to 100 percentage param = %lu\n", __func__, param[1]); rc = -EINVAL; goto afe_error; } param[1] = (Q6AFE_MAX_VOLUME * param[1]) / 100; if (this_afe.apr == NULL) { pr_err("%s: Error, AFE not opened\n", __func__); rc = -EINVAL; } else { rc = afe_loopback_gain(param[0], param[1]); } } else { pr_err("%s: Error, invalid parameters\n", __func__); rc = -EINVAL; } } afe_error: if (rc == 0) rc = cnt; else pr_err("%s: rc = %d\n", __func__, rc); return rc; }
int afe_unregister_get_events(u16 port_id) { int ret = 0; struct afe_service_cmd_unregister_rt_port_driver rtproxy; int index = 0; pr_debug("%s:\n", __func__); if (this_afe.apr == NULL) { this_afe.apr = apr_register("ADSP", "AFE", afe_callback, 0xFFFFFFFF, &this_afe); pr_debug("%s: Register AFE\n", __func__); if (this_afe.apr == NULL) { pr_err("%s: Unable to register AFE\n", __func__); ret = -ENODEV; return ret; } } index = q6audio_get_port_index(port_id); if (q6audio_validate_port(port_id) < 0) return -EINVAL; if ((port_id == RT_PROXY_DAI_002_RX) || (port_id == RT_PROXY_DAI_001_TX)) port_id = VIRTUAL_ID_TO_PORTID(port_id); else return -EINVAL; rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); rtproxy.hdr.pkt_size = sizeof(rtproxy); rtproxy.hdr.src_port = 0; rtproxy.hdr.dest_port = 0; rtproxy.hdr.token = 0; rtproxy.hdr.opcode = AFE_SERVICE_CMD_UNREGISTER_RT_PORT_DRIVER; rtproxy.port_id = port_id; rtproxy.reserved = 0; rtproxy.hdr.token = index; if (port_id == RT_PROXY_PORT_001_TX) { this_afe.tx_cb = NULL; this_afe.tx_private_data = NULL; } else if (port_id == RT_PROXY_PORT_001_RX) { this_afe.rx_cb = NULL; this_afe.rx_private_data = NULL; } atomic_set(&this_afe.state, 1); ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy); if (ret < 0) { pr_err("%s: AFE enable Unreg. rtproxy_event failed %d\n", __func__, ret); ret = -EINVAL; return ret; } ret = wait_event_timeout(this_afe.wait[index], (atomic_read(&this_afe.state) == 0), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); ret = -EINVAL; return ret; } return 0; }