audio: add support for routing to/from voice TX/RX paths
Add support for routing voice calls to devices in other audio
HALs by allowing playback and captuer to/from AFE proxy.
Bug: 15520724.
Change-Id: Ia4a4428001ea06f7c7b213db861ec281ebd25174
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 9eddfb6..0c6c3f8 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -58,6 +58,9 @@
#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
+#define PROXY_OPEN_RETRY_COUNT 100
+#define PROXY_OPEN_WAIT_TIME 20
+
static unsigned int configured_low_latency_capture_period_size =
LOW_LATENCY_CAPTURE_PERIOD_SIZE;
@@ -105,6 +108,37 @@
.format = PCM_FORMAT_S16_LE,
};
+#define AFE_PROXY_CHANNEL_COUNT 2
+#define AFE_PROXY_SAMPLING_RATE 48000
+
+#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
+#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
+
+struct pcm_config pcm_config_afe_proxy_playback = {
+ .channels = AFE_PROXY_CHANNEL_COUNT,
+ .rate = AFE_PROXY_SAMPLING_RATE,
+ .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
+ .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
+ .format = PCM_FORMAT_S16_LE,
+ .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
+ .stop_threshold = INT_MAX,
+ .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
+};
+
+#define AFE_PROXY_RECORD_PERIOD_SIZE 768
+#define AFE_PROXY_RECORD_PERIOD_COUNT 4
+
+struct pcm_config pcm_config_afe_proxy_record = {
+ .channels = AFE_PROXY_CHANNEL_COUNT,
+ .rate = AFE_PROXY_SAMPLING_RATE,
+ .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
+ .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
+ .format = PCM_FORMAT_S16_LE,
+ .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
+ .stop_threshold = INT_MAX,
+ .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
+};
+
const char * const use_case_table[AUDIO_USECASE_MAX] = {
[USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
[USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
@@ -122,6 +156,9 @@
[USECASE_VOLTE_CALL] = "volte-call",
[USECASE_QCHAT_CALL] = "qchat-call",
[USECASE_VOWLAN_CALL] = "vowlan-call",
+
+ [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
+ [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
};
@@ -536,14 +573,14 @@
usecase->devices = usecase->stream.in->device;
out_snd_device = SND_DEVICE_NONE;
if (in_snd_device == SND_DEVICE_NONE) {
+ audio_devices_t out_device = AUDIO_DEVICE_NONE;
if (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
adev->primary_output && !adev->primary_output->standby) {
- in_snd_device = platform_get_input_snd_device(adev->platform,
- adev->primary_output->devices);
- } else {
- in_snd_device = platform_get_input_snd_device(adev->platform,
- AUDIO_DEVICE_NONE);
+ out_device = adev->primary_output->devices;
+ } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
+ out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
}
+ in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
}
}
}
@@ -680,15 +717,34 @@
ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
__func__, adev->snd_card, in->pcm_device_id, in->config.channels);
- in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
- PCM_IN, &in->config);
- if (in->pcm && !pcm_is_ready(in->pcm)) {
- ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
- pcm_close(in->pcm);
- in->pcm = NULL;
- ret = -EIO;
- goto error_open;
+
+ unsigned int flags = PCM_IN;
+ unsigned int pcm_open_retry_count = 0;
+
+ if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
+ flags |= PCM_MMAP | PCM_NOIRQ;
+ pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
}
+
+ while (1) {
+ in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
+ flags, &in->config);
+ if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
+ ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
+ if (in->pcm != NULL) {
+ pcm_close(in->pcm);
+ in->pcm = NULL;
+ }
+ if (pcm_open_retry_count-- == 0) {
+ ret = -EIO;
+ goto error_open;
+ }
+ usleep(PROXY_OPEN_WAIT_TIME * 1000);
+ continue;
+ }
+ break;
+ }
+
ALOGV("%s: exit", __func__);
return ret;
@@ -989,14 +1045,31 @@
ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
__func__, adev->snd_card, out->pcm_device_id, out->config.format);
if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
- out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
- PCM_OUT | PCM_MONOTONIC, &out->config);
- if (out->pcm && !pcm_is_ready(out->pcm)) {
- ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
- pcm_close(out->pcm);
- out->pcm = NULL;
- ret = -EIO;
- goto error_open;
+ unsigned int flags = PCM_OUT;
+ unsigned int pcm_open_retry_count = 0;
+ if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
+ flags |= PCM_MMAP | PCM_NOIRQ;
+ pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
+ } else
+ flags |= PCM_MONOTONIC;
+
+ while (1) {
+ out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
+ flags, &out->config);
+ if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
+ ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
+ if (out->pcm != NULL) {
+ pcm_close(out->pcm);
+ out->pcm = NULL;
+ }
+ if (pcm_open_retry_count-- == 0) {
+ ret = -EIO;
+ goto error_open;
+ }
+ usleep(PROXY_OPEN_WAIT_TIME * 1000);
+ continue;
+ }
+ break;
}
} else {
out->pcm = NULL;
@@ -1096,7 +1169,6 @@
if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
return out->compr_config.fragment_size;
}
-
return out->config.period_size *
audio_stream_out_frame_size((const struct audio_stream_out *)stream);
}
@@ -1191,6 +1263,10 @@
return 0;
}
+static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
+{
+ return out == adev->primary_output || out == adev->voice_tx_output;
+}
static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
{
@@ -1250,20 +1326,24 @@
select_devices(adev, out->usecase);
if ((adev->mode == AUDIO_MODE_IN_CALL) &&
- !voice_is_in_call(adev) &&
- (out == adev->primary_output)) {
- ret = voice_start_call(adev);
- } else if ((adev->mode == AUDIO_MODE_IN_CALL) &&
- voice_is_in_call(adev) &&
- (out == adev->primary_output)) {
- voice_update_devices_for_all_voice_usecases(adev);
+ output_drives_call(adev, out)) {
+
+ if (adev->current_call_output != out) {
+ voice_stop_call(adev);
+ }
+ if (!voice_is_in_call(adev)) {
+ ret = voice_start_call(adev, out);
+ adev->current_call_output = out;
+ } else
+ voice_update_devices_for_all_voice_usecases(adev);
}
}
if ((adev->mode == AUDIO_MODE_NORMAL) &&
voice_is_in_call(adev) &&
- (out == adev->primary_output)) {
+ output_drives_call(adev, out)) {
ret = voice_stop_call(adev);
+ adev->current_call_output = NULL;
}
pthread_mutex_unlock(&adev->lock);
@@ -1412,7 +1492,11 @@
if (out->muted)
memset((void *)buffer, 0, bytes);
ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
- ret = pcm_write(out->pcm, (void *)buffer, bytes);
+ if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
+ ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
+ }
+ else
+ ret = pcm_write(out->pcm, (void *)buffer, bytes);
if (ret == 0)
out->written += bytes / (out->config.channels * sizeof(short));
}
@@ -1682,7 +1766,7 @@
if (ret >= 0) {
val = atoi(value);
- if ((in->device != val) && (val != 0)) {
+ if (((int)in->device != val) && (val != 0)) {
in->device = val;
/* If recording is in progress, change the tx device to new device */
if (!in->standby)
@@ -1728,7 +1812,10 @@
}
if (in->pcm) {
- ret = pcm_read(in->pcm, buffer, bytes);
+ if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
+ ret = pcm_mmap_read(in->pcm, buffer, bytes);
+ } else
+ ret = pcm_read(in->pcm, buffer, bytes);
}
/*
@@ -1897,6 +1984,28 @@
ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
__func__, config->offload_info.version,
config->offload_info.bit_rate);
+ } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
+ if (config->sample_rate == 0)
+ config->sample_rate = AFE_PROXY_SAMPLING_RATE;
+ if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
+ config->sample_rate != 8000) {
+ config->sample_rate = AFE_PROXY_SAMPLING_RATE;
+ ret = -EINVAL;
+ goto error_open;
+ }
+ out->sample_rate = config->sample_rate;
+ out->config.rate = config->sample_rate;
+ if (config->format == AUDIO_FORMAT_DEFAULT)
+ config->format = AUDIO_FORMAT_PCM_16_BIT;
+ if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
+ config->format = AUDIO_FORMAT_PCM_16_BIT;
+ ret = -EINVAL;
+ goto error_open;
+ }
+ out->format = config->format;
+ out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
+ out->config = pcm_config_afe_proxy_playback;
+ adev->voice_tx_output = out;
} else {
if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
@@ -1926,7 +2035,7 @@
__func__, use_case_table[out->usecase], config->format, out->config.format);
if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
- if(adev->primary_output == NULL)
+ if (adev->primary_output == NULL)
adev->primary_output = out;
else {
ALOGE("%s: Primary output is already opened", __func__);
@@ -2205,6 +2314,7 @@
struct stream_in *in;
int ret = 0, buffer_size, frame_size;
int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
+ bool is_low_latency = false;
ALOGV("%s: enter", __func__);
*stream_in = NULL;
@@ -2238,25 +2348,46 @@
in->channel_mask = config->channel_mask;
/* Update config params with the requested sample rate and channels */
- in->usecase = USECASE_AUDIO_RECORD;
- bool is_low_latency = false;
- if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
- (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
- is_low_latency = true;
+ if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
+ if (config->sample_rate == 0)
+ config->sample_rate = AFE_PROXY_SAMPLING_RATE;
+ if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
+ config->sample_rate != 8000) {
+ config->sample_rate = AFE_PROXY_SAMPLING_RATE;
+ ret = -EINVAL;
+ goto err_open;
+ }
+ if (config->format == AUDIO_FORMAT_DEFAULT)
+ config->format = AUDIO_FORMAT_PCM_16_BIT;
+ if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
+ config->format = AUDIO_FORMAT_PCM_16_BIT;
+ ret = -EINVAL;
+ goto err_open;
+ }
+
+ in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
+ in->config = pcm_config_afe_proxy_record;
+ } else {
+ in->usecase = USECASE_AUDIO_RECORD;
+ if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
+ (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
+ is_low_latency = true;
#if LOW_LATENCY_CAPTURE_USE_CASE
- in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
+ in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
#endif
+ }
+ in->config = pcm_config_audio_capture;
+
+ frame_size = audio_stream_in_frame_size(&in->stream);
+ buffer_size = get_input_buffer_size(config->sample_rate,
+ config->format,
+ channel_count,
+ is_low_latency);
+ in->config.period_size = buffer_size / frame_size;
}
- in->config = pcm_config_audio_capture;
in->config.channels = channel_count;
in->config.rate = config->sample_rate;
- frame_size = audio_stream_in_frame_size(&in->stream);
- buffer_size = get_input_buffer_size(config->sample_rate,
- config->format,
- channel_count,
- is_low_latency);
- in->config.period_size = buffer_size / frame_size;
*stream_in = &in->stream;
ALOGV("%s: exit", __func__);
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 62bc100..8940f5b 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -75,6 +75,10 @@
USECASE_INCALL_REC_UPLINK,
USECASE_INCALL_REC_DOWNLINK,
USECASE_INCALL_REC_UPLINK_AND_DOWNLINK,
+
+ USECASE_AUDIO_PLAYBACK_AFE_PROXY,
+ USECASE_AUDIO_RECORD_AFE_PROXY,
+
AUDIO_USECASE_MAX
} audio_usecase_t;
@@ -154,7 +158,7 @@
int standby;
int source;
int pcm_device_id;
- int device;
+ audio_devices_t device;
audio_channel_mask_t channel_mask;
audio_usecase_t usecase;
bool enable_aec;
@@ -191,6 +195,8 @@
audio_mode_t mode;
struct stream_in *active_input;
struct stream_out *primary_output;
+ struct stream_out *voice_tx_output;
+ struct stream_out *current_call_output;
bool bluetooth_nrec;
bool screen_off;
int *snd_dev_ref_cnt;
diff --git a/hal/msm8960/platform.h b/hal/msm8960/platform.h
index 4d137aa..0201772 100644
--- a/hal/msm8960/platform.h
+++ b/hal/msm8960/platform.h
@@ -120,4 +120,8 @@
#define LOW_LATENCY_CAPTURE_PERIOD_SIZE 240
#define LOW_LATENCY_CAPTURE_USE_CASE 0
+#define AFE_PROXY_PLAYBACK_PCM_DEVICE 7
+#define AFE_PROXY_RECORD_PCM_DEVICE 8
+
+
#endif // QCOM_AUDIO_PLATFORM_H
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index c835c6b..ad28f6b 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -117,6 +117,12 @@
[USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = {AUDIO_RECORD_PCM_DEVICE,
AUDIO_RECORD_PCM_DEVICE},
[USECASE_AUDIO_HFP_SCO] = {HFP_PCM_RX, HFP_SCO_RX},
+
+ [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = {AFE_PROXY_PLAYBACK_PCM_DEVICE,
+ AFE_PROXY_RECORD_PCM_DEVICE},
+ [USECASE_AUDIO_RECORD_AFE_PROXY] = {AFE_PROXY_PLAYBACK_PCM_DEVICE,
+ AFE_PROXY_RECORD_PCM_DEVICE},
+
};
/* Array to store sound devices */
@@ -142,6 +148,7 @@
[SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = "voice-tty-full-headphones",
[SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = "voice-tty-vco-headphones",
[SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = "voice-tty-hco-handset",
+ [SND_DEVICE_OUT_VOICE_TX] = "voice-tx",
/* Capture sound devices */
[SND_DEVICE_IN_HANDSET_MIC] = "handset-mic",
@@ -169,6 +176,7 @@
[SND_DEVICE_IN_VOICE_REC_DMIC_BS] = "voice-rec-dmic-bs",
[SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE] = "voice-rec-dmic-ef-fluence",
[SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE] = "voice-rec-dmic-bs-fluence",
+ [SND_DEVICE_IN_VOICE_RX] = "voice-rx",
};
/* ACDB IDs (audio DSP path configuration IDs) for each sound device */
@@ -198,6 +206,7 @@
[SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = 17,
[SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = 17,
[SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = 37,
+ [SND_DEVICE_OUT_VOICE_TX] = 45,
[SND_DEVICE_IN_HANDSET_MIC] = 4,
[SND_DEVICE_IN_SPEAKER_MIC] = 4, /* ToDo: Check if this needs to changed to 11 */
@@ -225,6 +234,7 @@
[SND_DEVICE_IN_VOICE_REC_DMIC_BS] = 62,
[SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE] = 6,
[SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE] = 5,
+ [SND_DEVICE_IN_VOICE_RX] = 44,
};
struct name_to_index {
@@ -542,6 +552,8 @@
backend_table[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = strdup("speaker-and-hdmi");
backend_table[SND_DEVICE_OUT_BT_SCO_WB] = strdup("bt-sco-wb");
backend_table[SND_DEVICE_IN_BT_SCO_MIC_WB] = strdup("bt-sco-wb");
+ backend_table[SND_DEVICE_OUT_VOICE_TX] = strdup("afe-proxy");
+ backend_table[SND_DEVICE_IN_VOICE_RX] = strdup("afe-proxy");
if (my_data->ext_speaker) {
backend_table[SND_DEVICE_OUT_SPEAKER] = strdup("speaker");
@@ -1124,7 +1136,9 @@
snd_device = SND_DEVICE_OUT_VOICE_HANDSET_TMUS;
else
snd_device = SND_DEVICE_OUT_VOICE_HANDSET;
- }
+ } else if (devices & AUDIO_DEVICE_OUT_TELEPHONY_TX)
+ snd_device = SND_DEVICE_OUT_VOICE_TX;
+
if (snd_device != SND_DEVICE_NONE) {
goto exit;
}
@@ -1262,7 +1276,8 @@
} else {
snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
}
- }
+ } else if (out_device & AUDIO_DEVICE_OUT_TELEPHONY_TX)
+ snd_device = SND_DEVICE_IN_VOICE_RX;
} else if (source == AUDIO_SOURCE_CAMCORDER) {
if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
in_device & AUDIO_DEVICE_IN_BACK_MIC) {
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index bbb90a7..fd00c96 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -55,6 +55,7 @@
SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES,
SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET,
SND_DEVICE_OUT_VOICE_HAC_HANDSET,
+ SND_DEVICE_OUT_VOICE_TX,
SND_DEVICE_OUT_END,
/*
@@ -88,6 +89,7 @@
SND_DEVICE_IN_VOICE_REC_DMIC_BS,
SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE,
SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE,
+ SND_DEVICE_IN_VOICE_RX,
SND_DEVICE_IN_END,
SND_DEVICE_MAX = SND_DEVICE_IN_END,
@@ -158,6 +160,9 @@
#define VOWLAN_CALL_PCM_DEVICE 36
#endif
+#define AFE_PROXY_PLAYBACK_PCM_DEVICE 7
+#define AFE_PROXY_RECORD_PCM_DEVICE 8
+
#define HFP_PCM_RX 5
#ifdef PLATFORM_MSM8x26
#define HFP_SCO_RX 28
diff --git a/hal/voice.c b/hal/voice.c
index ecc607d..4b72df3 100644
--- a/hal/voice.c
+++ b/hal/voice.c
@@ -97,7 +97,7 @@
return ret;
}
-int start_call(struct audio_device *adev, audio_usecase_t usecase_id)
+int start_call(struct audio_device *adev, audio_usecase_t usecase_id, struct stream_out *out)
{
int i, ret = 0;
struct audio_usecase *uc_info;
@@ -112,8 +112,8 @@
uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
uc_info->id = usecase_id;
uc_info->type = VOICE_CALL;
- uc_info->stream.out = adev->primary_output;
- uc_info->devices = adev->primary_output->devices;
+ uc_info->stream.out = out;
+ uc_info->devices = out->devices;
uc_info->in_snd_device = SND_DEVICE_NONE;
uc_info->out_snd_device = SND_DEVICE_NONE;
@@ -327,13 +327,13 @@
return err;
}
-int voice_start_call(struct audio_device *adev)
+int voice_start_call(struct audio_device *adev, struct stream_out *out)
{
int ret = 0;
ret = voice_extn_start_call(adev);
if (ret == -ENOSYS) {
- ret = start_call(adev, USECASE_VOICE_CALL);
+ ret = start_call(adev, USECASE_VOICE_CALL, out);
}
return ret;
diff --git a/hal/voice.h b/hal/voice.h
index 11f3be0..6b3bb07 100644
--- a/hal/voice.h
+++ b/hal/voice.h
@@ -68,7 +68,7 @@
INCALL_REC_UPLINK_AND_DOWNLINK,
};
-int voice_start_call(struct audio_device *adev);
+int voice_start_call(struct audio_device *adev, struct stream_out *out);
int voice_stop_call(struct audio_device *adev);
int voice_set_parameters(struct audio_device *adev, struct str_parms *parms);
void voice_get_parameters(struct audio_device *adev, struct str_parms *query,