int adm_connect_afe_port(int mode, int session_id, int port_id) { struct adm_cmd_connect_afe_port cmd; int ret = 0; int index; pr_debug("%s: port %d session id:%d mode:%d\n", __func__, port_id, session_id, mode); port_id = afe_convert_virtual_to_portid(port_id); if (afe_validate_port(port_id) < 0) { pr_err("%s port idi[%d] is invalid\n", __func__, port_id); return -ENODEV; } 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); } index = afe_get_port_index(port_id); pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index); cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cmd.hdr.pkt_size = sizeof(cmd); cmd.hdr.src_svc = APR_SVC_ADM; cmd.hdr.src_domain = APR_DOMAIN_APPS; cmd.hdr.src_port = port_id; cmd.hdr.dest_svc = APR_SVC_ADM; cmd.hdr.dest_domain = APR_DOMAIN_ADSP; cmd.hdr.dest_port = port_id; cmd.hdr.token = port_id; cmd.hdr.opcode = ADM_CMD_CONNECT_AFE_PORT; cmd.mode = mode; cmd.session_id = session_id; cmd.afe_port_id = port_id; atomic_set(&this_adm.copp_stat[index], 0); ret = apr_send_pkt(this_adm.apr, (uint32_t *)&cmd); if (ret < 0) { pr_err("%s:ADM enable for port %d failed\n", __func__, port_id); ret = -EINVAL; goto fail_cmd; } ret = wait_event_timeout(this_adm.wait, atomic_read(&this_adm.copp_stat[index]), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s ADM connect AFE failed for port %d\n", __func__, port_id); ret = -EINVAL; goto fail_cmd; } atomic_inc(&this_adm.copp_cnt[index]); return 0; fail_cmd: return ret; }
int adm_multi_ch_copp_open(int port_id, int path, int rate, int channel_mode, int topology, int perfmode) { struct adm_multi_ch_copp_open_command open; int ret = 0; int index; pr_debug("%s: port %d path:%d rate:%d channel :%d\n", __func__, port_id, path, rate, channel_mode); port_id = afe_convert_virtual_to_portid(port_id); if (afe_validate_port(port_id) < 0) { pr_err("%s port idi[%d] is invalid\n", __func__, port_id); return -ENODEV; } index = afe_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); } 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(struct adm_multi_ch_copp_open_command); if (perfmode) { pr_debug("%s Performance mode", __func__); open.hdr.opcode = ADM_CMD_MULTI_CHANNEL_COPP_OPEN_V3; open.flags = ADM_MULTI_CH_COPP_OPEN_PERF_MODE_BIT; open.reserved = PCM_BITS_PER_SAMPLE; } else { open.hdr.opcode = ADM_CMD_MULTI_CHANNEL_COPP_OPEN; open.reserved = 0; } 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 == 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 == 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 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_FLC; open.dev_channel_mapping[7] = PCM_CHANNEL_FRC; } else { pr_err("%s invalid num_chan %d\n", __func__, channel_mode); return -EINVAL; } open.hdr.src_svc = APR_SVC_ADM; open.hdr.src_domain = APR_DOMAIN_APPS; open.hdr.src_port = port_id; open.hdr.dest_svc = APR_SVC_ADM; open.hdr.dest_domain = APR_DOMAIN_ADSP; open.hdr.dest_port = port_id; open.hdr.token = port_id; open.mode = path; open.endpoint_id1 = port_id; if (this_adm.ec_ref_rx == 0) { open.endpoint_id2 = 0xFFFF; } else if (this_adm.ec_ref_rx && (path != 1)) { open.endpoint_id2 = this_adm.ec_ref_rx; this_adm.ec_ref_rx = 0; } pr_debug("%s open.endpoint_id1:%d open.endpoint_id2:%d", __func__, open.endpoint_id1, open.endpoint_id2); 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.channel_config = channel_mode & 0x00FF; open.rate = rate; pr_debug("%s: channel_config=%d port_id=%d rate=%d" " topology_id=0x%X\n", __func__, open.channel_config, open.endpoint_id1, open.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 failed\n", __func__, port_id); ret = -EINVAL; goto fail_cmd; } ret = wait_event_timeout(this_adm.wait, atomic_read(&this_adm.copp_stat[index]), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s ADM open failed for port %d\n", __func__, port_id); ret = -EINVAL; goto fail_cmd; } } atomic_inc(&this_adm.copp_cnt[index]); return 0; fail_cmd: return ret; }
int adm_close(int port_id) { struct apr_hdr close; int ret = 0; int index = 0; port_id = afe_convert_virtual_to_portid(port_id); index = afe_get_port_index(port_id); if (afe_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_COPP_CLOSE; 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, 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 afe_loopback_gain(u16 port_id, u16 volume) { struct afe_port_cmd_set_param set_param; int ret = 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 (afe_validate_port(port_id) < 0) { pr_err("%s: Failed : Invalid Port id = %d\n", __func__, port_id); ret = -EINVAL; goto fail_cmd; } /* 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 = 0; set_param.hdr.opcode = AFE_PORT_CMD_SET_PARAM; set_param.port_id = port_id; set_param.payload_size = sizeof(struct afe_param_payload_base) + sizeof(struct afe_param_loopback_gain); set_param.payload_address = 0; set_param.payload.base.module_id = AFE_MODULE_ID_PORT_INFO; set_param.payload.base.param_id = AFE_PARAM_ID_LOOPBACK_GAIN; set_param.payload.base.param_size = sizeof(struct afe_param_loopback_gain); set_param.payload.base.reserved = 0; set_param.payload.param.loopback_gain.gain = volume; set_param.payload.param.loopback_gain.reserved = 0; 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, (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; }
/* This function should be used by 8660 exclusively */ int afe_open(u16 port_id, union afe_port_config *afe_config, int rate) { struct afe_port_start_command start; struct afe_audioif_config_command config; int ret = 0; if (!afe_config) { pr_err("%s: Error, no configuration data\n", __func__); ret = -EINVAL; return ret; } pr_debug("%s: %d %d\n", __func__, port_id, rate); if ((port_id == RT_PROXY_DAI_001_RX) || (port_id == RT_PROXY_DAI_002_TX)) return 0; 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; 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 = afe_sizeof_cfg_cmd(port_id); config.hdr.src_port = 0; config.hdr.dest_port = 0; config.hdr.token = 0; switch (port_id) { 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: config.hdr.opcode = AFE_PORT_AUDIO_SLIM_SCH_CONFIG; break; case MI2S_TX: case MI2S_RX: case SECONDARY_I2S_RX: case SECONDARY_I2S_TX: case PRIMARY_I2S_RX: case PRIMARY_I2S_TX: /* AFE_PORT_CMD_I2S_CONFIG command is not supported * in the LPASS EL 1.0. So we have to distiguish * which AFE command, AFE_PORT_CMD_I2S_CONFIG or * AFE_PORT_AUDIO_IF_CONFIG to use. If the format * is L-PCM, the AFE_PORT_AUDIO_IF_CONFIG is used * to make the backward compatible. */ pr_debug("%s: afe_config->mi2s.format = %d\n", __func__, afe_config->mi2s.format); if (afe_config->mi2s.format == MSM_AFE_I2S_FORMAT_LPCM) config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG; else config.hdr.opcode = AFE_PORT_CMD_I2S_CONFIG; break; default: config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG; break; } if (afe_validate_port(port_id) < 0) { pr_err("%s: Failed : Invalid Port id = %d\n", __func__, port_id); ret = -EINVAL; goto fail_cmd; } config.port_id = port_id; config.port = *afe_config; 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 failed\n", __func__, port_id); ret = -EINVAL; goto fail_cmd; } ret = wait_event_timeout(this_afe.wait, (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 = 0; start.hdr.opcode = AFE_PORT_CMD_START; start.port_id = port_id; start.gain = 0x2000; start.sample_rate = rate; 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, (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 (this_afe.task != current) this_afe.task = current; pr_debug("task_name = %s pid = %d\n", this_afe.task->comm, this_afe.task->pid); 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 (!strcmp(lb_str, "afe_loopback")) { 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 ((afe_validate_port(param[1]) < 0) || (afe_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 (!strcmp(lb_str, "afe_loopback_gain")) { rc = afe_get_parameters(lbuf, param, 2); if (!rc) { pr_info("%s %lu %lu\n", lb_str, param[0], param[1]); if (afe_validate_port(param[0]) < 0) { pr_err("%s: Error, invalid afe port\n", __func__); rc = -EINVAL; goto afe_error; } if (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_apply_gain(u16 port_id, u16 gain) { struct afe_port_gain_command set_gain; int ret = 0; if (this_afe.apr == NULL) { pr_err("%s: AFE is not opened\n", __func__); ret = -EPERM; goto fail_cmd; } if (afe_validate_port(port_id) < 0) { pr_err("%s: Failed : Invalid Port id = %d\n", __func__, port_id); ret = -EINVAL; goto fail_cmd; } /* RX ports numbers are even .TX ports numbers are odd. */ if (port_id % 2 == 0) { pr_err("%s: Failed : afe apply 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, gain); set_gain.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); set_gain.hdr.pkt_size = sizeof(set_gain); set_gain.hdr.src_port = 0; set_gain.hdr.dest_port = 0; set_gain.hdr.token = 0; set_gain.hdr.opcode = AFE_PORT_CMD_APPLY_GAIN; set_gain.port_id = port_id; set_gain.gain = gain; atomic_set(&this_afe.state, 1); ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_gain); if (ret < 0) { pr_err("%s: AFE Gain set failed for port %d\n", __func__, port_id); ret = -EINVAL; goto fail_cmd; } ret = wait_event_timeout(this_afe.wait, (atomic_read(&this_afe.state) == 0), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); HTC_Q6_BUG(); ret = -EINVAL; goto fail_cmd; } return 0; fail_cmd: return ret; }
int adm_open(int port_id, int path, int rate, int channel_mode, int topology) { struct adm_copp_open_command open; int ret = 0; int index; pr_debug("%s: port %d path:%d rate:%d mode:%d\n", __func__, port_id, path, rate, channel_mode); port_id = afe_convert_virtual_to_portid(port_id); if (afe_validate_port(port_id) < 0) { pr_err("%s port idi[%d] is invalid\n", __func__, port_id); return -ENODEV; } index = afe_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 = port_id; open.hdr.dest_svc = APR_SVC_ADM; open.hdr.dest_domain = APR_DOMAIN_ADSP; open.hdr.dest_port = port_id; open.hdr.token = port_id; open.hdr.opcode = ADM_CMD_COPP_OPEN; open.mode = path; open.endpoint_id1 = port_id; open.endpoint_id2 = 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.channel_config = channel_mode & 0x00FF; open.rate = rate; pr_debug("%s: channel_config=%d port_id=%d rate=%d\ topology_id=0x%X\n", __func__, open.channel_config,\ open.endpoint_id1, open.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 failed\n", __func__, port_id); ret = -EINVAL; goto fail_cmd; } /* Wait for the callback with copp id */ ret = wait_event_timeout(this_adm.wait, atomic_read(&this_adm.copp_stat[index]), msecs_to_jiffies(3 * TIMEOUT_MS)); if (!ret) { #if 0 pr_err("%s ADM open failed for port %d\n", __func__, port_id); ret = -EINVAL; goto fail_cmd; #else // chenjun pr_err("chenjun:%s ADM open port %d always OK.\n", __func__, port_id); #endif } } atomic_inc(&this_adm.copp_cnt[index]); return 0; fail_cmd: return ret; }