Loading hal/audio_hw.c +270 −39 Original line number Original line Diff line number Diff line Loading @@ -131,6 +131,26 @@ struct pcm_config pcm_config_low_latency = { .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4, .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4, }; }; struct pcm_config pcm_config_haptics_audio = { .channels = 1, .rate = DEFAULT_OUTPUT_SAMPLING_RATE, .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE, .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT, .format = PCM_FORMAT_S16_LE, .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4, .stop_threshold = INT_MAX, .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4, }; struct pcm_config pcm_config_haptics = { .channels = 1, .rate = DEFAULT_OUTPUT_SAMPLING_RATE, .period_count = 2, .format = PCM_FORMAT_S16_LE, .stop_threshold = INT_MAX, .avail_min = 0, }; static int af_period_multiplier = 4; static int af_period_multiplier = 4; struct pcm_config pcm_config_rt = { struct pcm_config pcm_config_rt = { .channels = DEFAULT_CHANNEL_COUNT, .channels = DEFAULT_CHANNEL_COUNT, Loading Loading @@ -256,6 +276,7 @@ struct pcm_config pcm_config_afe_proxy_record = { const char * const use_case_table[AUDIO_USECASE_MAX] = { const char * const use_case_table[AUDIO_USECASE_MAX] = { [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback", [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback", [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback", [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback", [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback", [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback", [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback", [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback", [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback", [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback", [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback", Loading Loading @@ -1510,6 +1531,7 @@ int select_devices(struct audio_device *adev, get_voice_usecase_id_from_list(adev)); get_voice_usecase_id_from_list(adev)); if ((vc_usecase != NULL) && if ((vc_usecase != NULL) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) || ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) || (vc_usecase->devices == AUDIO_DEVICE_OUT_HEARING_AID) || (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) { (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) { in_snd_device = vc_usecase->in_snd_device; in_snd_device = vc_usecase->in_snd_device; out_snd_device = vc_usecase->out_snd_device; out_snd_device = vc_usecase->out_snd_device; Loading Loading @@ -1556,8 +1578,13 @@ int select_devices(struct audio_device *adev, out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX; out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX; } else if (voip_usecase) { } else if (voip_usecase) { out_device = voip_usecase->stream.out->devices; out_device = voip_usecase->stream.out->devices; } else if (adev->primary_output) { } else if (adev->primary_output && !adev->primary_output->standby) { out_device = adev->primary_output->devices; out_device = adev->primary_output->devices; } else { /* forcing speaker o/p device to get matching i/p pair in case o/p is not routed from same primary HAL */ out_device = AUDIO_DEVICE_OUT_SPEAKER; } } } } in_snd_device = platform_get_input_snd_device(adev->platform, in_snd_device = platform_get_input_snd_device(adev->platform, Loading Loading @@ -2213,14 +2240,19 @@ static int stop_output_stream(struct stream_out *out) } } ret = 0; ret = 0; } } /* 1) media + voip output routing to handset must route media back to speaker when voip stops. 2) trigger voip input to reroute when voip output changes to hearing aid. */ if (has_voip_usecase || if (has_voip_usecase || out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) { out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) { struct listnode *node; struct listnode *node; struct audio_usecase *usecase; struct audio_usecase *usecase; list_for_each(node, &adev->usecase_list) { list_for_each(node, &adev->usecase_list) { usecase = node_to_item(node, struct audio_usecase, list); usecase = node_to_item(node, struct audio_usecase, list); if (usecase->type == PCM_CAPTURE || usecase == uc_info) if ((usecase->type == PCM_CAPTURE && usecase->id != USECASE_AUDIO_RECORD_VOIP) || usecase == uc_info) continue; continue; ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)", ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)", Loading @@ -2235,6 +2267,41 @@ static int stop_output_stream(struct stream_out *out) return ret; return ret; } } struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id, unsigned int flags, unsigned int pcm_open_retry_count, struct pcm_config *config) { struct pcm* pcm = NULL; while (1) { pcm = pcm_open(snd_card, pcm_device_id, flags, config); if (pcm == NULL || !pcm_is_ready(pcm)) { ALOGE("%s: %s", __func__, pcm_get_error(pcm)); if (pcm != NULL) { pcm_close(pcm); pcm = NULL; } if (pcm_open_retry_count-- == 0) return NULL; usleep(PROXY_OPEN_WAIT_TIME * 1000); continue; } break; } if (pcm_is_ready(pcm)) { int ret = pcm_prepare(pcm); if (ret < 0) { ALOGE("%s: pcm_prepare returned %d", __func__, ret); pcm_close(pcm); pcm = NULL; } } return pcm; } int start_output_stream(struct stream_out *out) int start_output_stream(struct stream_out *out) { { int ret = 0; int ret = 0; Loading @@ -2242,8 +2309,10 @@ int start_output_stream(struct stream_out *out) struct audio_device *adev = out->dev; struct audio_device *adev = out->dev; bool a2dp_combo = false; bool a2dp_combo = false; ALOGV("%s: enter: usecase(%d: %s) devices(%#x)", ALOGV("%s: enter: usecase(%d: %s) %s devices(%#x)", __func__, out->usecase, use_case_table[out->usecase], out->devices); __func__, out->usecase, use_case_table[out->usecase], out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS ? "(with haptics)" : "", out->devices); if (out->card_status == CARD_STATUS_OFFLINE || if (out->card_status == CARD_STATUS_OFFLINE || adev->card_status == CARD_STATUS_OFFLINE) { adev->card_status == CARD_STATUS_OFFLINE) { Loading Loading @@ -2363,34 +2432,27 @@ int start_output_stream(struct stream_out *out) flags |= PCM_MMAP | PCM_NOIRQ; flags |= PCM_MMAP | PCM_NOIRQ; } } while (1) { out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id, out->pcm = pcm_open(adev->snd_card, out->pcm_device_id, flags, pcm_open_retry_count, flags, &out->config); &(out->config)); if (out->pcm == NULL || !pcm_is_ready(out->pcm)) { if (out->pcm == NULL) { 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; ret = -EIO; goto error_open; goto error_open; } } usleep(PROXY_OPEN_WAIT_TIME * 1000); continue; if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) { } if (adev->haptic_pcm != NULL) { break; pcm_close(adev->haptic_pcm); } adev->haptic_pcm = NULL; ALOGV("%s: pcm_prepare", __func__); if (pcm_is_ready(out->pcm)) { ret = pcm_prepare(out->pcm); if (ret < 0) { ALOGE("%s: pcm_prepare returned %d", __func__, ret); pcm_close(out->pcm); out->pcm = NULL; goto error_open; } } adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card, adev->haptic_pcm_device_id, flags, pcm_open_retry_count, &(adev->haptics_config)); // failure to open haptics pcm shouldnt stop audio, // so do not close audio pcm in case of error } } if (out->realtime) { if (out->realtime) { ret = pcm_start(out->pcm); ret = pcm_start(out->pcm); if (ret < 0) { if (ret < 0) { Loading @@ -2401,6 +2463,7 @@ int start_output_stream(struct stream_out *out) } } } } } } register_out_stream(out); register_out_stream(out); audio_streaming_hint_end(); audio_streaming_hint_end(); audio_extn_perf_lock_release(); audio_extn_perf_lock_release(); Loading @@ -2414,13 +2477,17 @@ int start_output_stream(struct stream_out *out) // consider a scenario where on pause lower layers are tear down. // consider a scenario where on pause lower layers are tear down. // so on resume, swap mixer control need to be sent only when // so on resume, swap mixer control need to be sent only when // backend is active, hence rather than sending from enable device // backend is active, hence rather than sending from enable device // sending it from start of streamtream // sending it from start of stream platform_set_swap_channels(adev, true); platform_set_swap_channels(adev, true); ALOGV("%s: exit", __func__); ALOGV("%s: exit", __func__); return 0; return 0; error_open: error_open: if (adev->haptic_pcm) { pcm_close(adev->haptic_pcm); adev->haptic_pcm = NULL; } audio_streaming_hint_end(); audio_streaming_hint_end(); audio_extn_perf_lock_release(); audio_extn_perf_lock_release(); stop_output_stream(out); stop_output_stream(out); Loading Loading @@ -2594,6 +2661,19 @@ static int out_standby_l(struct audio_stream *stream) if (out->pcm) { if (out->pcm) { pcm_close(out->pcm); pcm_close(out->pcm); out->pcm = NULL; out->pcm = NULL; if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) { if (adev->haptic_pcm) { pcm_close(adev->haptic_pcm); adev->haptic_pcm = NULL; } if (adev->haptic_buffer != NULL) { free(adev->haptic_buffer); adev->haptic_buffer = NULL; adev->haptic_buffer_size = 0; } } } } if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) { if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) { do_stop = out->playback_started; do_stop = out->playback_started; Loading Loading @@ -3294,11 +3374,77 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer, request_out_focus(out, ns); request_out_focus(out, ns); bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime; bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime; if (use_mmap) if (use_mmap) { ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write); ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write); else } else { ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write); if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) { size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask); size_t bytes_per_sample = audio_bytes_per_sample(out->format); size_t frame_size = channel_count * bytes_per_sample; size_t frame_count = bytes_to_write / frame_size; bool force_haptic_path = property_get_bool("vendor.audio.test_haptic", false); // extract Haptics data from Audio buffer bool alloc_haptic_buffer = false; int haptic_channel_count = adev->haptics_config.channels; size_t haptic_frame_size = bytes_per_sample * haptic_channel_count; size_t audio_frame_size = frame_size - haptic_frame_size; size_t total_haptic_buffer_size = frame_count * haptic_frame_size; if (adev->haptic_buffer == NULL) { alloc_haptic_buffer = true; } else if (adev->haptic_buffer_size < total_haptic_buffer_size) { free(adev->haptic_buffer); adev->haptic_buffer_size = 0; alloc_haptic_buffer = true; } if (alloc_haptic_buffer) { adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size); adev->haptic_buffer_size = total_haptic_buffer_size; } size_t src_index = 0, aud_index = 0, hap_index = 0; uint8_t *audio_buffer = (uint8_t *)buffer; uint8_t *haptic_buffer = adev->haptic_buffer; // This is required for testing only. This works for stereo data only. // One channel is fed to audio stream and other to haptic stream for testing. if (force_haptic_path) { audio_frame_size = haptic_frame_size = bytes_per_sample; } for (size_t i = 0; i < frame_count; i++) { for (size_t j = 0; j < audio_frame_size; j++) audio_buffer[aud_index++] = audio_buffer[src_index++]; for (size_t j = 0; j < haptic_frame_size; j++) haptic_buffer[hap_index++] = audio_buffer[src_index++]; } // This is required for testing only. // Discard haptic channel data. if (force_haptic_path) { src_index += haptic_frame_size; } // write to audio pipeline ret = pcm_write(out->pcm, (void *)audio_buffer, frame_count * audio_frame_size); // write to haptics pipeline if (adev->haptic_pcm) ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer, frame_count * haptic_frame_size); } else { ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write); } } release_out_focus(out, ns); release_out_focus(out, ns); } else { } else { LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream"); LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream"); Loading Loading @@ -4377,6 +4523,52 @@ static int in_set_microphone_field_dimension(const struct audio_stream_in *strea return -ENOSYS; return -ENOSYS; } } static void in_update_sink_metadata(struct audio_stream_in *stream, const struct sink_metadata *sink_metadata) { if (stream == NULL || sink_metadata == NULL || sink_metadata->tracks == NULL) { return; } int error = 0; struct stream_in *in = (struct stream_in *)stream; struct audio_device *adev = in->dev; audio_devices_t device = AUDIO_DEVICE_NONE; if (sink_metadata->track_count != 0) device = sink_metadata->tracks->dest_device; lock_input_stream(in); pthread_mutex_lock(&adev->lock); ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device); if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY && device != AUDIO_DEVICE_NONE && adev->voice_tx_output != NULL) { /* Use the rx device from afe-proxy record to route voice call because there is no routing if tx device is on primary hal and rx device is on other hal during voice call. */ adev->voice_tx_output->devices = device; if (!voice_is_call_state_active(adev)) { if (adev->mode == AUDIO_MODE_IN_CALL) { adev->current_call_output = adev->voice_tx_output; error = voice_start_call(adev); if (error != 0) ALOGE("%s: start voice call failed %d", __func__, error); } } else { adev->current_call_output = adev->voice_tx_output; voice_update_devices_for_all_voice_usecases(adev); } } pthread_mutex_unlock(&adev->lock); pthread_mutex_unlock(&in->lock); } static int adev_open_output_stream(struct audio_hw_device *dev, static int adev_open_output_stream(struct audio_hw_device *dev, audio_io_handle_t handle, audio_io_handle_t handle, audio_devices_t devices, audio_devices_t devices, Loading @@ -4391,6 +4583,8 @@ static int adev_open_output_stream(struct audio_hw_device *dev, bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL; bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL; bool is_usb_dev = audio_is_usb_out_device(devices) && bool is_usb_dev = audio_is_usb_out_device(devices) && (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY); (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY); bool force_haptic_path = property_get_bool("vendor.audio.test_haptic", false); if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) { if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) { return -ENOSYS; return -ENOSYS; Loading @@ -4398,6 +4592,7 @@ static int adev_open_output_stream(struct audio_hw_device *dev, ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)", ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)", __func__, config->format, config->sample_rate, config->channel_mask, devices, flags); __func__, config->format, config->sample_rate, config->channel_mask, devices, flags); *stream_out = NULL; *stream_out = NULL; out = (struct stream_out *)calloc(1, sizeof(struct stream_out)); out = (struct stream_out *)calloc(1, sizeof(struct stream_out)); Loading Loading @@ -4727,21 +4922,39 @@ static int adev_open_output_stream(struct audio_hw_device *dev, out->stream.stop = out_stop; out->stream.stop = out_stop; out->stream.create_mmap_buffer = out_create_mmap_buffer; out->stream.create_mmap_buffer = out_create_mmap_buffer; out->stream.get_mmap_position = out_get_mmap_position; out->stream.get_mmap_position = out_get_mmap_position; } else { if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) { out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS; adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id(); if (adev->haptic_pcm_device_id < 0) { ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)", __func__, adev->haptic_pcm_device_id, out->usecase); ret = -ENOSYS; goto error_open; } out->config = pcm_config_haptics_audio; if (force_haptic_path) adev->haptics_config = pcm_config_haptics_audio; else adev->haptics_config = pcm_config_haptics; } else { } else { out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY; out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY; out->config = pcm_config_low_latency; out->config = pcm_config_low_latency; } } } if (config->sample_rate == 0) { if (config->sample_rate == 0) { out->sample_rate = out->config.rate; out->sample_rate = out->config.rate; } else { } else { out->sample_rate = config->sample_rate; out->sample_rate = config->sample_rate; } } if (config->channel_mask == AUDIO_CHANNEL_NONE) { if (config->channel_mask == AUDIO_CHANNEL_NONE) { out->channel_mask = audio_channel_out_mask_from_count(out->config.channels); out->channel_mask = audio_channel_out_mask_from_count(out->config.channels); } else { } else { out->channel_mask = config->channel_mask; out->channel_mask = config->channel_mask; } } if (config->format == AUDIO_FORMAT_DEFAULT) if (config->format == AUDIO_FORMAT_DEFAULT) out->format = audio_format_from_pcm_format(out->config.format); out->format = audio_format_from_pcm_format(out->config.format); else if (!audio_is_linear_pcm(config->format)) { else if (!audio_is_linear_pcm(config->format)) { Loading @@ -4753,8 +4966,25 @@ static int adev_open_output_stream(struct audio_hw_device *dev, } } out->config.rate = out->sample_rate; out->config.rate = out->sample_rate; if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) { out->config.channels = audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL); if (force_haptic_path) { out->config.channels = 1; adev->haptics_config.channels = 1; } else { adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL); } } else { out->config.channels = out->config.channels = audio_channel_count_from_out_mask(out->channel_mask); audio_channel_count_from_out_mask(out->channel_mask); } if (out->format != audio_format_from_pcm_format(out->config.format)) { if (out->format != audio_format_from_pcm_format(out->config.format)) { out->config.format = pcm_format_from_audio_format(out->format); out->config.format = pcm_format_from_audio_format(out->format); } } Loading Loading @@ -5306,6 +5536,7 @@ static int adev_open_input_stream(struct audio_hw_device *dev, in->stream.get_active_microphones = in_get_active_microphones; in->stream.get_active_microphones = in_get_active_microphones; in->stream.set_microphone_direction = in_set_microphone_direction; in->stream.set_microphone_direction = in_set_microphone_direction; in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension; in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension; in->stream.update_sink_metadata = in_update_sink_metadata; in->device = devices; in->device = devices; in->source = source; in->source = source; Loading hal/audio_hw.h +8 −0 Original line number Original line Diff line number Diff line Loading @@ -82,6 +82,7 @@ enum { USECASE_AUDIO_PLAYBACK_TTS, USECASE_AUDIO_PLAYBACK_TTS, USECASE_AUDIO_PLAYBACK_ULL, USECASE_AUDIO_PLAYBACK_ULL, USECASE_AUDIO_PLAYBACK_MMAP, USECASE_AUDIO_PLAYBACK_MMAP, USECASE_AUDIO_PLAYBACK_WITH_HAPTICS, /* HFP Use case*/ /* HFP Use case*/ USECASE_AUDIO_HFP_SCO, USECASE_AUDIO_HFP_SCO, Loading Loading @@ -381,6 +382,13 @@ struct audio_device { void *adm_data; void *adm_data; void *adm_lib; void *adm_lib; struct pcm_config haptics_config; struct pcm *haptic_pcm; int haptic_pcm_device_id; uint8_t *haptic_buffer; size_t haptic_buffer_size; adm_init_t adm_init; adm_init_t adm_init; adm_deinit_t adm_deinit; adm_deinit_t adm_deinit; adm_register_input_stream_t adm_register_input_stream; adm_register_input_stream_t adm_register_input_stream; Loading hal/msm8916/platform.c +5 −0 Original line number Original line Diff line number Diff line Loading @@ -1401,6 +1401,11 @@ int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type) return device_id; return device_id; } } int platform_get_haptics_pcm_device_id() { return -1; } static int find_index(struct name_to_index * table, int32_t len, const char * name) static int find_index(struct name_to_index * table, int32_t len, const char * name) { { int ret = 0; int ret = 0; Loading hal/msm8960/platform.c +5 −0 Original line number Original line Diff line number Diff line Loading @@ -424,6 +424,11 @@ int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type) return device_id; return device_id; } } int platform_get_haptics_pcm_device_id() { return -1; } int platform_get_snd_device_index(char *snd_device_index_name __unused) int platform_get_snd_device_index(char *snd_device_index_name __unused) { { return -ENODEV; return -ENODEV; Loading hal/msm8974/platform.c +30 −1 Original line number Original line Diff line number Diff line Loading @@ -184,6 +184,8 @@ struct platform_data { static int pcm_device_table[AUDIO_USECASE_MAX][2] = { static int pcm_device_table[AUDIO_USECASE_MAX][2] = { [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {DEEP_BUFFER_PCM_DEVICE, [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {DEEP_BUFFER_PCM_DEVICE, DEEP_BUFFER_PCM_DEVICE}, DEEP_BUFFER_PCM_DEVICE}, [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = {AUDIO_HAPTICS_PCM_DEVICE, AUDIO_HAPTICS_PCM_DEVICE}, [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE, [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE, LOWLATENCY_PCM_DEVICE}, LOWLATENCY_PCM_DEVICE}, [USECASE_AUDIO_PLAYBACK_HIFI] = {MULTIMEDIA2_PCM_DEVICE, [USECASE_AUDIO_PLAYBACK_HIFI] = {MULTIMEDIA2_PCM_DEVICE, Loading Loading @@ -293,6 +295,7 @@ static const char * const device_table[SND_DEVICE_MAX] = { [SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO] = "speaker-safe-and-bt-sco", [SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO] = "speaker-safe-and-bt-sco", [SND_DEVICE_OUT_SPEAKER_AND_BT_SCO_WB] = "speaker-and-bt-sco-wb", [SND_DEVICE_OUT_SPEAKER_AND_BT_SCO_WB] = "speaker-and-bt-sco-wb", [SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_WB] = "speaker-safe-and-bt-sco-wb", [SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_WB] = "speaker-safe-and-bt-sco-wb", [SND_DEVICE_OUT_VOICE_HEARING_AID] = "hearing-aid", /* Capture sound devices */ /* Capture sound devices */ [SND_DEVICE_IN_HANDSET_MIC] = "handset-mic", [SND_DEVICE_IN_HANDSET_MIC] = "handset-mic", Loading Loading @@ -372,6 +375,7 @@ static const char * const device_table[SND_DEVICE_MAX] = { [SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT] = "camcorder-mic", [SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT] = "camcorder-mic", [SND_DEVICE_IN_SPEAKER_QMIC_NS] = "quad-mic", [SND_DEVICE_IN_SPEAKER_QMIC_NS] = "quad-mic", [SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS] = "quad-mic", [SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS] = "quad-mic", [SND_DEVICE_IN_VOICE_HEARING_AID] = "hearing-aid-mic", }; }; static struct audio_effect_config \ static struct audio_effect_config \ Loading Loading @@ -444,6 +448,7 @@ static int acdb_device_table[SND_DEVICE_MAX] = { [SND_DEVICE_OUT_SPEAKER_PROTECTED] = 124, [SND_DEVICE_OUT_SPEAKER_PROTECTED] = 124, [SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED] = 101, [SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED] = 101, [SND_DEVICE_OUT_VOICE_SPEAKER_HFP] = ACDB_ID_VOICE_SPEAKER, [SND_DEVICE_OUT_VOICE_SPEAKER_HFP] = ACDB_ID_VOICE_SPEAKER, [SND_DEVICE_OUT_VOICE_HEARING_AID] = 45, [SND_DEVICE_IN_HANDSET_MIC] = 4, [SND_DEVICE_IN_HANDSET_MIC] = 4, [SND_DEVICE_IN_HANDSET_MIC_AEC] = 106, [SND_DEVICE_IN_HANDSET_MIC_AEC] = 106, Loading Loading @@ -521,6 +526,7 @@ static int acdb_device_table[SND_DEVICE_MAX] = { [SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT] = 61, [SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT] = 61, [SND_DEVICE_IN_SPEAKER_QMIC_NS] = 129, [SND_DEVICE_IN_SPEAKER_QMIC_NS] = 129, [SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS] = 129, [SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS] = 129, [SND_DEVICE_IN_VOICE_HEARING_AID] = 44, }; }; // Platform specific backend bit width table // Platform specific backend bit width table Loading Loading @@ -579,6 +585,7 @@ static const struct name_to_index snd_device_name_index[SND_DEVICE_MAX] = { {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_PROTECTED)}, {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_PROTECTED)}, {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED)}, {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED)}, {TO_NAME_INDEX(SND_DEVICE_OUT_USB_HEADSET_SPEC)}, {TO_NAME_INDEX(SND_DEVICE_OUT_USB_HEADSET_SPEC)}, {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HEARING_AID)}, /* in */ /* in */ {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC)}, {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC)}, Loading Loading @@ -655,6 +662,8 @@ static const struct name_to_index snd_device_name_index[SND_DEVICE_MAX] = { {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_SELFIE_LANDSCAPE)}, {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_SELFIE_LANDSCAPE)}, {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_SELFIE_INVERT_LANDSCAPE)}, {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_SELFIE_INVERT_LANDSCAPE)}, {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT)}, {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT)}, {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_HEARING_AID)}, /* For legacy xml file parsing */ /* For legacy xml file parsing */ {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_MIC)}, {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_MIC)}, {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_NS)}, {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_NS)}, Loading @@ -667,6 +676,7 @@ static char * hw_interface_table[SND_DEVICE_MAX] = {0}; static const struct name_to_index usecase_name_index[AUDIO_USECASE_MAX] = { static const struct name_to_index usecase_name_index[AUDIO_USECASE_MAX] = { {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_DEEP_BUFFER)}, {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_DEEP_BUFFER)}, {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_LOW_LATENCY)}, {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_LOW_LATENCY)}, {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)}, {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_HIFI)}, {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_HIFI)}, {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD)}, {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD)}, {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_TTS)}, {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_TTS)}, Loading Loading @@ -1285,6 +1295,7 @@ static void set_platform_defaults(struct platform_data * my_data) backend_tag_table[SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP] = strdup("speaker-and-bt-a2dp"); backend_tag_table[SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP] = strdup("speaker-and-bt-a2dp"); backend_tag_table[SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP] = strdup("speaker-safe-and-bt-a2dp"); backend_tag_table[SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP] = strdup("speaker-safe-and-bt-a2dp"); backend_tag_table[SND_DEVICE_OUT_USB_HEADSET_SPEC] = strdup("usb-headset"); backend_tag_table[SND_DEVICE_OUT_USB_HEADSET_SPEC] = strdup("usb-headset"); backend_tag_table[SND_DEVICE_OUT_VOICE_HEARING_AID] = strdup("hearing-aid"); hw_interface_table[SND_DEVICE_OUT_HANDSET] = strdup("SLIMBUS_0_RX"); hw_interface_table[SND_DEVICE_OUT_HANDSET] = strdup("SLIMBUS_0_RX"); hw_interface_table[SND_DEVICE_OUT_SPEAKER] = strdup("SLIMBUS_0_RX"); hw_interface_table[SND_DEVICE_OUT_SPEAKER] = strdup("SLIMBUS_0_RX"); Loading Loading @@ -1333,6 +1344,11 @@ static void set_platform_defaults(struct platform_data * my_data) hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_BT_SCO_WB] = strdup("SLIMBUS_0_RX-and-SEC_AUX_PCM_RX"); hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_BT_SCO_WB] = strdup("SLIMBUS_0_RX-and-SEC_AUX_PCM_RX"); hw_interface_table[SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO] = strdup("QUAT_TDM_RX_0-and-SLIMBUS_7_RX"), hw_interface_table[SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO] = strdup("QUAT_TDM_RX_0-and-SLIMBUS_7_RX"), hw_interface_table[SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_WB] = strdup("QUAT_TDM_RX_0-and-SLIMBUS_7_RX"), hw_interface_table[SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_WB] = strdup("QUAT_TDM_RX_0-and-SLIMBUS_7_RX"), /* So far, primary hal doesn't support hearing aid device. Need snd_device to route voice call and use specific acdb tuning. Also, BT_RX is a virtual port to indicate bluetooth hearing aid. */ hw_interface_table[SND_DEVICE_OUT_VOICE_HEARING_AID] = strdup("BT_RX"), hw_interface_table[SND_DEVICE_IN_USB_HEADSET_MIC] = strdup("USB_AUDIO_TX"); hw_interface_table[SND_DEVICE_IN_USB_HEADSET_MIC] = strdup("USB_AUDIO_TX"); hw_interface_table[SND_DEVICE_IN_VOICE_USB_HEADSET_MIC] = strdup("USB_AUDIO_TX"); hw_interface_table[SND_DEVICE_IN_VOICE_USB_HEADSET_MIC] = strdup("USB_AUDIO_TX"); hw_interface_table[SND_DEVICE_IN_USB_HEADSET_MIC_AEC] = strdup("USB_AUDIO_TX"); hw_interface_table[SND_DEVICE_IN_USB_HEADSET_MIC_AEC] = strdup("USB_AUDIO_TX"); Loading Loading @@ -1400,6 +1416,8 @@ static void set_platform_defaults(struct platform_data * my_data) hw_interface_table[SND_DEVICE_IN_CAMCORDER_SELFIE_LANDSCAPE] = strdup("SLIMBUS_0_TX"); hw_interface_table[SND_DEVICE_IN_CAMCORDER_SELFIE_LANDSCAPE] = strdup("SLIMBUS_0_TX"); hw_interface_table[SND_DEVICE_IN_CAMCORDER_SELFIE_INVERT_LANDSCAPE] = strdup("SLIMBUS_0_TX"); hw_interface_table[SND_DEVICE_IN_CAMCORDER_SELFIE_INVERT_LANDSCAPE] = strdup("SLIMBUS_0_TX"); hw_interface_table[SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT] = strdup("SLIMBUS_0_TX"); hw_interface_table[SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT] = strdup("SLIMBUS_0_TX"); hw_interface_table[SND_DEVICE_IN_VOICE_HEARING_AID] = strdup("SLIMBUS_0_TX"); my_data->max_mic_count = PLATFORM_DEFAULT_MIC_COUNT; my_data->max_mic_count = PLATFORM_DEFAULT_MIC_COUNT; } } Loading Loading @@ -2060,6 +2078,11 @@ int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type) return device_id; return device_id; } } int platform_get_haptics_pcm_device_id() { return HAPTICS_PCM_DEVICE; } static int find_index(const struct name_to_index * table, int32_t len, static int find_index(const struct name_to_index * table, int32_t len, const char * name) const char * name) { { Loading Loading @@ -2893,8 +2916,11 @@ snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devi snd_device = SND_DEVICE_OUT_VOICE_HANDSET_TMUS; snd_device = SND_DEVICE_OUT_VOICE_HANDSET_TMUS; else else snd_device = SND_DEVICE_OUT_VOICE_HANDSET; snd_device = SND_DEVICE_OUT_VOICE_HANDSET; } else if (devices & AUDIO_DEVICE_OUT_TELEPHONY_TX) } else if (devices & AUDIO_DEVICE_OUT_TELEPHONY_TX) { snd_device = SND_DEVICE_OUT_VOICE_TX; snd_device = SND_DEVICE_OUT_VOICE_TX; } else if (devices & AUDIO_DEVICE_OUT_HEARING_AID) { snd_device = SND_DEVICE_OUT_VOICE_HEARING_AID; } if (snd_device != SND_DEVICE_NONE) { if (snd_device != SND_DEVICE_NONE) { goto exit; goto exit; Loading Loading @@ -3186,6 +3212,8 @@ snd_device_t platform_get_input_snd_device(void *platform, snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC; snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC; } } } } } else if (out_device & AUDIO_DEVICE_OUT_HEARING_AID) { snd_device = SND_DEVICE_IN_VOICE_HEARING_AID; } } } else if (source == AUDIO_SOURCE_CAMCORDER) { } else if (source == AUDIO_SOURCE_CAMCORDER) { if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC || if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC || Loading Loading @@ -3702,6 +3730,7 @@ int64_t platform_render_latency(audio_usecase_t usecase) case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER: case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER: return DEEP_BUFFER_PLATFORM_DELAY; return DEEP_BUFFER_PLATFORM_DELAY; case USECASE_AUDIO_PLAYBACK_LOW_LATENCY: case USECASE_AUDIO_PLAYBACK_LOW_LATENCY: case USECASE_AUDIO_PLAYBACK_WITH_HAPTICS: return LOW_LATENCY_PLATFORM_DELAY; return LOW_LATENCY_PLATFORM_DELAY; case USECASE_AUDIO_PLAYBACK_ULL: case USECASE_AUDIO_PLAYBACK_ULL: return ULL_PLATFORM_DELAY; return ULL_PLATFORM_DELAY; Loading Loading
hal/audio_hw.c +270 −39 Original line number Original line Diff line number Diff line Loading @@ -131,6 +131,26 @@ struct pcm_config pcm_config_low_latency = { .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4, .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4, }; }; struct pcm_config pcm_config_haptics_audio = { .channels = 1, .rate = DEFAULT_OUTPUT_SAMPLING_RATE, .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE, .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT, .format = PCM_FORMAT_S16_LE, .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4, .stop_threshold = INT_MAX, .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4, }; struct pcm_config pcm_config_haptics = { .channels = 1, .rate = DEFAULT_OUTPUT_SAMPLING_RATE, .period_count = 2, .format = PCM_FORMAT_S16_LE, .stop_threshold = INT_MAX, .avail_min = 0, }; static int af_period_multiplier = 4; static int af_period_multiplier = 4; struct pcm_config pcm_config_rt = { struct pcm_config pcm_config_rt = { .channels = DEFAULT_CHANNEL_COUNT, .channels = DEFAULT_CHANNEL_COUNT, Loading Loading @@ -256,6 +276,7 @@ struct pcm_config pcm_config_afe_proxy_record = { const char * const use_case_table[AUDIO_USECASE_MAX] = { const char * const use_case_table[AUDIO_USECASE_MAX] = { [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback", [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback", [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback", [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback", [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback", [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback", [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback", [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback", [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback", [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback", [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback", Loading Loading @@ -1510,6 +1531,7 @@ int select_devices(struct audio_device *adev, get_voice_usecase_id_from_list(adev)); get_voice_usecase_id_from_list(adev)); if ((vc_usecase != NULL) && if ((vc_usecase != NULL) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) || ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) || (vc_usecase->devices == AUDIO_DEVICE_OUT_HEARING_AID) || (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) { (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) { in_snd_device = vc_usecase->in_snd_device; in_snd_device = vc_usecase->in_snd_device; out_snd_device = vc_usecase->out_snd_device; out_snd_device = vc_usecase->out_snd_device; Loading Loading @@ -1556,8 +1578,13 @@ int select_devices(struct audio_device *adev, out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX; out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX; } else if (voip_usecase) { } else if (voip_usecase) { out_device = voip_usecase->stream.out->devices; out_device = voip_usecase->stream.out->devices; } else if (adev->primary_output) { } else if (adev->primary_output && !adev->primary_output->standby) { out_device = adev->primary_output->devices; out_device = adev->primary_output->devices; } else { /* forcing speaker o/p device to get matching i/p pair in case o/p is not routed from same primary HAL */ out_device = AUDIO_DEVICE_OUT_SPEAKER; } } } } in_snd_device = platform_get_input_snd_device(adev->platform, in_snd_device = platform_get_input_snd_device(adev->platform, Loading Loading @@ -2213,14 +2240,19 @@ static int stop_output_stream(struct stream_out *out) } } ret = 0; ret = 0; } } /* 1) media + voip output routing to handset must route media back to speaker when voip stops. 2) trigger voip input to reroute when voip output changes to hearing aid. */ if (has_voip_usecase || if (has_voip_usecase || out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) { out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) { struct listnode *node; struct listnode *node; struct audio_usecase *usecase; struct audio_usecase *usecase; list_for_each(node, &adev->usecase_list) { list_for_each(node, &adev->usecase_list) { usecase = node_to_item(node, struct audio_usecase, list); usecase = node_to_item(node, struct audio_usecase, list); if (usecase->type == PCM_CAPTURE || usecase == uc_info) if ((usecase->type == PCM_CAPTURE && usecase->id != USECASE_AUDIO_RECORD_VOIP) || usecase == uc_info) continue; continue; ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)", ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)", Loading @@ -2235,6 +2267,41 @@ static int stop_output_stream(struct stream_out *out) return ret; return ret; } } struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id, unsigned int flags, unsigned int pcm_open_retry_count, struct pcm_config *config) { struct pcm* pcm = NULL; while (1) { pcm = pcm_open(snd_card, pcm_device_id, flags, config); if (pcm == NULL || !pcm_is_ready(pcm)) { ALOGE("%s: %s", __func__, pcm_get_error(pcm)); if (pcm != NULL) { pcm_close(pcm); pcm = NULL; } if (pcm_open_retry_count-- == 0) return NULL; usleep(PROXY_OPEN_WAIT_TIME * 1000); continue; } break; } if (pcm_is_ready(pcm)) { int ret = pcm_prepare(pcm); if (ret < 0) { ALOGE("%s: pcm_prepare returned %d", __func__, ret); pcm_close(pcm); pcm = NULL; } } return pcm; } int start_output_stream(struct stream_out *out) int start_output_stream(struct stream_out *out) { { int ret = 0; int ret = 0; Loading @@ -2242,8 +2309,10 @@ int start_output_stream(struct stream_out *out) struct audio_device *adev = out->dev; struct audio_device *adev = out->dev; bool a2dp_combo = false; bool a2dp_combo = false; ALOGV("%s: enter: usecase(%d: %s) devices(%#x)", ALOGV("%s: enter: usecase(%d: %s) %s devices(%#x)", __func__, out->usecase, use_case_table[out->usecase], out->devices); __func__, out->usecase, use_case_table[out->usecase], out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS ? "(with haptics)" : "", out->devices); if (out->card_status == CARD_STATUS_OFFLINE || if (out->card_status == CARD_STATUS_OFFLINE || adev->card_status == CARD_STATUS_OFFLINE) { adev->card_status == CARD_STATUS_OFFLINE) { Loading Loading @@ -2363,34 +2432,27 @@ int start_output_stream(struct stream_out *out) flags |= PCM_MMAP | PCM_NOIRQ; flags |= PCM_MMAP | PCM_NOIRQ; } } while (1) { out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id, out->pcm = pcm_open(adev->snd_card, out->pcm_device_id, flags, pcm_open_retry_count, flags, &out->config); &(out->config)); if (out->pcm == NULL || !pcm_is_ready(out->pcm)) { if (out->pcm == NULL) { 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; ret = -EIO; goto error_open; goto error_open; } } usleep(PROXY_OPEN_WAIT_TIME * 1000); continue; if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) { } if (adev->haptic_pcm != NULL) { break; pcm_close(adev->haptic_pcm); } adev->haptic_pcm = NULL; ALOGV("%s: pcm_prepare", __func__); if (pcm_is_ready(out->pcm)) { ret = pcm_prepare(out->pcm); if (ret < 0) { ALOGE("%s: pcm_prepare returned %d", __func__, ret); pcm_close(out->pcm); out->pcm = NULL; goto error_open; } } adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card, adev->haptic_pcm_device_id, flags, pcm_open_retry_count, &(adev->haptics_config)); // failure to open haptics pcm shouldnt stop audio, // so do not close audio pcm in case of error } } if (out->realtime) { if (out->realtime) { ret = pcm_start(out->pcm); ret = pcm_start(out->pcm); if (ret < 0) { if (ret < 0) { Loading @@ -2401,6 +2463,7 @@ int start_output_stream(struct stream_out *out) } } } } } } register_out_stream(out); register_out_stream(out); audio_streaming_hint_end(); audio_streaming_hint_end(); audio_extn_perf_lock_release(); audio_extn_perf_lock_release(); Loading @@ -2414,13 +2477,17 @@ int start_output_stream(struct stream_out *out) // consider a scenario where on pause lower layers are tear down. // consider a scenario where on pause lower layers are tear down. // so on resume, swap mixer control need to be sent only when // so on resume, swap mixer control need to be sent only when // backend is active, hence rather than sending from enable device // backend is active, hence rather than sending from enable device // sending it from start of streamtream // sending it from start of stream platform_set_swap_channels(adev, true); platform_set_swap_channels(adev, true); ALOGV("%s: exit", __func__); ALOGV("%s: exit", __func__); return 0; return 0; error_open: error_open: if (adev->haptic_pcm) { pcm_close(adev->haptic_pcm); adev->haptic_pcm = NULL; } audio_streaming_hint_end(); audio_streaming_hint_end(); audio_extn_perf_lock_release(); audio_extn_perf_lock_release(); stop_output_stream(out); stop_output_stream(out); Loading Loading @@ -2594,6 +2661,19 @@ static int out_standby_l(struct audio_stream *stream) if (out->pcm) { if (out->pcm) { pcm_close(out->pcm); pcm_close(out->pcm); out->pcm = NULL; out->pcm = NULL; if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) { if (adev->haptic_pcm) { pcm_close(adev->haptic_pcm); adev->haptic_pcm = NULL; } if (adev->haptic_buffer != NULL) { free(adev->haptic_buffer); adev->haptic_buffer = NULL; adev->haptic_buffer_size = 0; } } } } if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) { if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) { do_stop = out->playback_started; do_stop = out->playback_started; Loading Loading @@ -3294,11 +3374,77 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer, request_out_focus(out, ns); request_out_focus(out, ns); bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime; bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime; if (use_mmap) if (use_mmap) { ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write); ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write); else } else { ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write); if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) { size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask); size_t bytes_per_sample = audio_bytes_per_sample(out->format); size_t frame_size = channel_count * bytes_per_sample; size_t frame_count = bytes_to_write / frame_size; bool force_haptic_path = property_get_bool("vendor.audio.test_haptic", false); // extract Haptics data from Audio buffer bool alloc_haptic_buffer = false; int haptic_channel_count = adev->haptics_config.channels; size_t haptic_frame_size = bytes_per_sample * haptic_channel_count; size_t audio_frame_size = frame_size - haptic_frame_size; size_t total_haptic_buffer_size = frame_count * haptic_frame_size; if (adev->haptic_buffer == NULL) { alloc_haptic_buffer = true; } else if (adev->haptic_buffer_size < total_haptic_buffer_size) { free(adev->haptic_buffer); adev->haptic_buffer_size = 0; alloc_haptic_buffer = true; } if (alloc_haptic_buffer) { adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size); adev->haptic_buffer_size = total_haptic_buffer_size; } size_t src_index = 0, aud_index = 0, hap_index = 0; uint8_t *audio_buffer = (uint8_t *)buffer; uint8_t *haptic_buffer = adev->haptic_buffer; // This is required for testing only. This works for stereo data only. // One channel is fed to audio stream and other to haptic stream for testing. if (force_haptic_path) { audio_frame_size = haptic_frame_size = bytes_per_sample; } for (size_t i = 0; i < frame_count; i++) { for (size_t j = 0; j < audio_frame_size; j++) audio_buffer[aud_index++] = audio_buffer[src_index++]; for (size_t j = 0; j < haptic_frame_size; j++) haptic_buffer[hap_index++] = audio_buffer[src_index++]; } // This is required for testing only. // Discard haptic channel data. if (force_haptic_path) { src_index += haptic_frame_size; } // write to audio pipeline ret = pcm_write(out->pcm, (void *)audio_buffer, frame_count * audio_frame_size); // write to haptics pipeline if (adev->haptic_pcm) ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer, frame_count * haptic_frame_size); } else { ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write); } } release_out_focus(out, ns); release_out_focus(out, ns); } else { } else { LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream"); LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream"); Loading Loading @@ -4377,6 +4523,52 @@ static int in_set_microphone_field_dimension(const struct audio_stream_in *strea return -ENOSYS; return -ENOSYS; } } static void in_update_sink_metadata(struct audio_stream_in *stream, const struct sink_metadata *sink_metadata) { if (stream == NULL || sink_metadata == NULL || sink_metadata->tracks == NULL) { return; } int error = 0; struct stream_in *in = (struct stream_in *)stream; struct audio_device *adev = in->dev; audio_devices_t device = AUDIO_DEVICE_NONE; if (sink_metadata->track_count != 0) device = sink_metadata->tracks->dest_device; lock_input_stream(in); pthread_mutex_lock(&adev->lock); ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device); if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY && device != AUDIO_DEVICE_NONE && adev->voice_tx_output != NULL) { /* Use the rx device from afe-proxy record to route voice call because there is no routing if tx device is on primary hal and rx device is on other hal during voice call. */ adev->voice_tx_output->devices = device; if (!voice_is_call_state_active(adev)) { if (adev->mode == AUDIO_MODE_IN_CALL) { adev->current_call_output = adev->voice_tx_output; error = voice_start_call(adev); if (error != 0) ALOGE("%s: start voice call failed %d", __func__, error); } } else { adev->current_call_output = adev->voice_tx_output; voice_update_devices_for_all_voice_usecases(adev); } } pthread_mutex_unlock(&adev->lock); pthread_mutex_unlock(&in->lock); } static int adev_open_output_stream(struct audio_hw_device *dev, static int adev_open_output_stream(struct audio_hw_device *dev, audio_io_handle_t handle, audio_io_handle_t handle, audio_devices_t devices, audio_devices_t devices, Loading @@ -4391,6 +4583,8 @@ static int adev_open_output_stream(struct audio_hw_device *dev, bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL; bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL; bool is_usb_dev = audio_is_usb_out_device(devices) && bool is_usb_dev = audio_is_usb_out_device(devices) && (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY); (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY); bool force_haptic_path = property_get_bool("vendor.audio.test_haptic", false); if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) { if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) { return -ENOSYS; return -ENOSYS; Loading @@ -4398,6 +4592,7 @@ static int adev_open_output_stream(struct audio_hw_device *dev, ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)", ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)", __func__, config->format, config->sample_rate, config->channel_mask, devices, flags); __func__, config->format, config->sample_rate, config->channel_mask, devices, flags); *stream_out = NULL; *stream_out = NULL; out = (struct stream_out *)calloc(1, sizeof(struct stream_out)); out = (struct stream_out *)calloc(1, sizeof(struct stream_out)); Loading Loading @@ -4727,21 +4922,39 @@ static int adev_open_output_stream(struct audio_hw_device *dev, out->stream.stop = out_stop; out->stream.stop = out_stop; out->stream.create_mmap_buffer = out_create_mmap_buffer; out->stream.create_mmap_buffer = out_create_mmap_buffer; out->stream.get_mmap_position = out_get_mmap_position; out->stream.get_mmap_position = out_get_mmap_position; } else { if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) { out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS; adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id(); if (adev->haptic_pcm_device_id < 0) { ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)", __func__, adev->haptic_pcm_device_id, out->usecase); ret = -ENOSYS; goto error_open; } out->config = pcm_config_haptics_audio; if (force_haptic_path) adev->haptics_config = pcm_config_haptics_audio; else adev->haptics_config = pcm_config_haptics; } else { } else { out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY; out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY; out->config = pcm_config_low_latency; out->config = pcm_config_low_latency; } } } if (config->sample_rate == 0) { if (config->sample_rate == 0) { out->sample_rate = out->config.rate; out->sample_rate = out->config.rate; } else { } else { out->sample_rate = config->sample_rate; out->sample_rate = config->sample_rate; } } if (config->channel_mask == AUDIO_CHANNEL_NONE) { if (config->channel_mask == AUDIO_CHANNEL_NONE) { out->channel_mask = audio_channel_out_mask_from_count(out->config.channels); out->channel_mask = audio_channel_out_mask_from_count(out->config.channels); } else { } else { out->channel_mask = config->channel_mask; out->channel_mask = config->channel_mask; } } if (config->format == AUDIO_FORMAT_DEFAULT) if (config->format == AUDIO_FORMAT_DEFAULT) out->format = audio_format_from_pcm_format(out->config.format); out->format = audio_format_from_pcm_format(out->config.format); else if (!audio_is_linear_pcm(config->format)) { else if (!audio_is_linear_pcm(config->format)) { Loading @@ -4753,8 +4966,25 @@ static int adev_open_output_stream(struct audio_hw_device *dev, } } out->config.rate = out->sample_rate; out->config.rate = out->sample_rate; if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) { out->config.channels = audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL); if (force_haptic_path) { out->config.channels = 1; adev->haptics_config.channels = 1; } else { adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL); } } else { out->config.channels = out->config.channels = audio_channel_count_from_out_mask(out->channel_mask); audio_channel_count_from_out_mask(out->channel_mask); } if (out->format != audio_format_from_pcm_format(out->config.format)) { if (out->format != audio_format_from_pcm_format(out->config.format)) { out->config.format = pcm_format_from_audio_format(out->format); out->config.format = pcm_format_from_audio_format(out->format); } } Loading Loading @@ -5306,6 +5536,7 @@ static int adev_open_input_stream(struct audio_hw_device *dev, in->stream.get_active_microphones = in_get_active_microphones; in->stream.get_active_microphones = in_get_active_microphones; in->stream.set_microphone_direction = in_set_microphone_direction; in->stream.set_microphone_direction = in_set_microphone_direction; in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension; in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension; in->stream.update_sink_metadata = in_update_sink_metadata; in->device = devices; in->device = devices; in->source = source; in->source = source; Loading
hal/audio_hw.h +8 −0 Original line number Original line Diff line number Diff line Loading @@ -82,6 +82,7 @@ enum { USECASE_AUDIO_PLAYBACK_TTS, USECASE_AUDIO_PLAYBACK_TTS, USECASE_AUDIO_PLAYBACK_ULL, USECASE_AUDIO_PLAYBACK_ULL, USECASE_AUDIO_PLAYBACK_MMAP, USECASE_AUDIO_PLAYBACK_MMAP, USECASE_AUDIO_PLAYBACK_WITH_HAPTICS, /* HFP Use case*/ /* HFP Use case*/ USECASE_AUDIO_HFP_SCO, USECASE_AUDIO_HFP_SCO, Loading Loading @@ -381,6 +382,13 @@ struct audio_device { void *adm_data; void *adm_data; void *adm_lib; void *adm_lib; struct pcm_config haptics_config; struct pcm *haptic_pcm; int haptic_pcm_device_id; uint8_t *haptic_buffer; size_t haptic_buffer_size; adm_init_t adm_init; adm_init_t adm_init; adm_deinit_t adm_deinit; adm_deinit_t adm_deinit; adm_register_input_stream_t adm_register_input_stream; adm_register_input_stream_t adm_register_input_stream; Loading
hal/msm8916/platform.c +5 −0 Original line number Original line Diff line number Diff line Loading @@ -1401,6 +1401,11 @@ int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type) return device_id; return device_id; } } int platform_get_haptics_pcm_device_id() { return -1; } static int find_index(struct name_to_index * table, int32_t len, const char * name) static int find_index(struct name_to_index * table, int32_t len, const char * name) { { int ret = 0; int ret = 0; Loading
hal/msm8960/platform.c +5 −0 Original line number Original line Diff line number Diff line Loading @@ -424,6 +424,11 @@ int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type) return device_id; return device_id; } } int platform_get_haptics_pcm_device_id() { return -1; } int platform_get_snd_device_index(char *snd_device_index_name __unused) int platform_get_snd_device_index(char *snd_device_index_name __unused) { { return -ENODEV; return -ENODEV; Loading
hal/msm8974/platform.c +30 −1 Original line number Original line Diff line number Diff line Loading @@ -184,6 +184,8 @@ struct platform_data { static int pcm_device_table[AUDIO_USECASE_MAX][2] = { static int pcm_device_table[AUDIO_USECASE_MAX][2] = { [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {DEEP_BUFFER_PCM_DEVICE, [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {DEEP_BUFFER_PCM_DEVICE, DEEP_BUFFER_PCM_DEVICE}, DEEP_BUFFER_PCM_DEVICE}, [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = {AUDIO_HAPTICS_PCM_DEVICE, AUDIO_HAPTICS_PCM_DEVICE}, [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE, [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE, LOWLATENCY_PCM_DEVICE}, LOWLATENCY_PCM_DEVICE}, [USECASE_AUDIO_PLAYBACK_HIFI] = {MULTIMEDIA2_PCM_DEVICE, [USECASE_AUDIO_PLAYBACK_HIFI] = {MULTIMEDIA2_PCM_DEVICE, Loading Loading @@ -293,6 +295,7 @@ static const char * const device_table[SND_DEVICE_MAX] = { [SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO] = "speaker-safe-and-bt-sco", [SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO] = "speaker-safe-and-bt-sco", [SND_DEVICE_OUT_SPEAKER_AND_BT_SCO_WB] = "speaker-and-bt-sco-wb", [SND_DEVICE_OUT_SPEAKER_AND_BT_SCO_WB] = "speaker-and-bt-sco-wb", [SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_WB] = "speaker-safe-and-bt-sco-wb", [SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_WB] = "speaker-safe-and-bt-sco-wb", [SND_DEVICE_OUT_VOICE_HEARING_AID] = "hearing-aid", /* Capture sound devices */ /* Capture sound devices */ [SND_DEVICE_IN_HANDSET_MIC] = "handset-mic", [SND_DEVICE_IN_HANDSET_MIC] = "handset-mic", Loading Loading @@ -372,6 +375,7 @@ static const char * const device_table[SND_DEVICE_MAX] = { [SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT] = "camcorder-mic", [SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT] = "camcorder-mic", [SND_DEVICE_IN_SPEAKER_QMIC_NS] = "quad-mic", [SND_DEVICE_IN_SPEAKER_QMIC_NS] = "quad-mic", [SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS] = "quad-mic", [SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS] = "quad-mic", [SND_DEVICE_IN_VOICE_HEARING_AID] = "hearing-aid-mic", }; }; static struct audio_effect_config \ static struct audio_effect_config \ Loading Loading @@ -444,6 +448,7 @@ static int acdb_device_table[SND_DEVICE_MAX] = { [SND_DEVICE_OUT_SPEAKER_PROTECTED] = 124, [SND_DEVICE_OUT_SPEAKER_PROTECTED] = 124, [SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED] = 101, [SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED] = 101, [SND_DEVICE_OUT_VOICE_SPEAKER_HFP] = ACDB_ID_VOICE_SPEAKER, [SND_DEVICE_OUT_VOICE_SPEAKER_HFP] = ACDB_ID_VOICE_SPEAKER, [SND_DEVICE_OUT_VOICE_HEARING_AID] = 45, [SND_DEVICE_IN_HANDSET_MIC] = 4, [SND_DEVICE_IN_HANDSET_MIC] = 4, [SND_DEVICE_IN_HANDSET_MIC_AEC] = 106, [SND_DEVICE_IN_HANDSET_MIC_AEC] = 106, Loading Loading @@ -521,6 +526,7 @@ static int acdb_device_table[SND_DEVICE_MAX] = { [SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT] = 61, [SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT] = 61, [SND_DEVICE_IN_SPEAKER_QMIC_NS] = 129, [SND_DEVICE_IN_SPEAKER_QMIC_NS] = 129, [SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS] = 129, [SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS] = 129, [SND_DEVICE_IN_VOICE_HEARING_AID] = 44, }; }; // Platform specific backend bit width table // Platform specific backend bit width table Loading Loading @@ -579,6 +585,7 @@ static const struct name_to_index snd_device_name_index[SND_DEVICE_MAX] = { {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_PROTECTED)}, {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_PROTECTED)}, {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED)}, {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED)}, {TO_NAME_INDEX(SND_DEVICE_OUT_USB_HEADSET_SPEC)}, {TO_NAME_INDEX(SND_DEVICE_OUT_USB_HEADSET_SPEC)}, {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HEARING_AID)}, /* in */ /* in */ {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC)}, {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC)}, Loading Loading @@ -655,6 +662,8 @@ static const struct name_to_index snd_device_name_index[SND_DEVICE_MAX] = { {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_SELFIE_LANDSCAPE)}, {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_SELFIE_LANDSCAPE)}, {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_SELFIE_INVERT_LANDSCAPE)}, {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_SELFIE_INVERT_LANDSCAPE)}, {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT)}, {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT)}, {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_HEARING_AID)}, /* For legacy xml file parsing */ /* For legacy xml file parsing */ {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_MIC)}, {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_MIC)}, {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_NS)}, {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_NS)}, Loading @@ -667,6 +676,7 @@ static char * hw_interface_table[SND_DEVICE_MAX] = {0}; static const struct name_to_index usecase_name_index[AUDIO_USECASE_MAX] = { static const struct name_to_index usecase_name_index[AUDIO_USECASE_MAX] = { {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_DEEP_BUFFER)}, {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_DEEP_BUFFER)}, {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_LOW_LATENCY)}, {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_LOW_LATENCY)}, {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)}, {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_HIFI)}, {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_HIFI)}, {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD)}, {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD)}, {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_TTS)}, {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_TTS)}, Loading Loading @@ -1285,6 +1295,7 @@ static void set_platform_defaults(struct platform_data * my_data) backend_tag_table[SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP] = strdup("speaker-and-bt-a2dp"); backend_tag_table[SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP] = strdup("speaker-and-bt-a2dp"); backend_tag_table[SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP] = strdup("speaker-safe-and-bt-a2dp"); backend_tag_table[SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP] = strdup("speaker-safe-and-bt-a2dp"); backend_tag_table[SND_DEVICE_OUT_USB_HEADSET_SPEC] = strdup("usb-headset"); backend_tag_table[SND_DEVICE_OUT_USB_HEADSET_SPEC] = strdup("usb-headset"); backend_tag_table[SND_DEVICE_OUT_VOICE_HEARING_AID] = strdup("hearing-aid"); hw_interface_table[SND_DEVICE_OUT_HANDSET] = strdup("SLIMBUS_0_RX"); hw_interface_table[SND_DEVICE_OUT_HANDSET] = strdup("SLIMBUS_0_RX"); hw_interface_table[SND_DEVICE_OUT_SPEAKER] = strdup("SLIMBUS_0_RX"); hw_interface_table[SND_DEVICE_OUT_SPEAKER] = strdup("SLIMBUS_0_RX"); Loading Loading @@ -1333,6 +1344,11 @@ static void set_platform_defaults(struct platform_data * my_data) hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_BT_SCO_WB] = strdup("SLIMBUS_0_RX-and-SEC_AUX_PCM_RX"); hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_BT_SCO_WB] = strdup("SLIMBUS_0_RX-and-SEC_AUX_PCM_RX"); hw_interface_table[SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO] = strdup("QUAT_TDM_RX_0-and-SLIMBUS_7_RX"), hw_interface_table[SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO] = strdup("QUAT_TDM_RX_0-and-SLIMBUS_7_RX"), hw_interface_table[SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_WB] = strdup("QUAT_TDM_RX_0-and-SLIMBUS_7_RX"), hw_interface_table[SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_WB] = strdup("QUAT_TDM_RX_0-and-SLIMBUS_7_RX"), /* So far, primary hal doesn't support hearing aid device. Need snd_device to route voice call and use specific acdb tuning. Also, BT_RX is a virtual port to indicate bluetooth hearing aid. */ hw_interface_table[SND_DEVICE_OUT_VOICE_HEARING_AID] = strdup("BT_RX"), hw_interface_table[SND_DEVICE_IN_USB_HEADSET_MIC] = strdup("USB_AUDIO_TX"); hw_interface_table[SND_DEVICE_IN_USB_HEADSET_MIC] = strdup("USB_AUDIO_TX"); hw_interface_table[SND_DEVICE_IN_VOICE_USB_HEADSET_MIC] = strdup("USB_AUDIO_TX"); hw_interface_table[SND_DEVICE_IN_VOICE_USB_HEADSET_MIC] = strdup("USB_AUDIO_TX"); hw_interface_table[SND_DEVICE_IN_USB_HEADSET_MIC_AEC] = strdup("USB_AUDIO_TX"); hw_interface_table[SND_DEVICE_IN_USB_HEADSET_MIC_AEC] = strdup("USB_AUDIO_TX"); Loading Loading @@ -1400,6 +1416,8 @@ static void set_platform_defaults(struct platform_data * my_data) hw_interface_table[SND_DEVICE_IN_CAMCORDER_SELFIE_LANDSCAPE] = strdup("SLIMBUS_0_TX"); hw_interface_table[SND_DEVICE_IN_CAMCORDER_SELFIE_LANDSCAPE] = strdup("SLIMBUS_0_TX"); hw_interface_table[SND_DEVICE_IN_CAMCORDER_SELFIE_INVERT_LANDSCAPE] = strdup("SLIMBUS_0_TX"); hw_interface_table[SND_DEVICE_IN_CAMCORDER_SELFIE_INVERT_LANDSCAPE] = strdup("SLIMBUS_0_TX"); hw_interface_table[SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT] = strdup("SLIMBUS_0_TX"); hw_interface_table[SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT] = strdup("SLIMBUS_0_TX"); hw_interface_table[SND_DEVICE_IN_VOICE_HEARING_AID] = strdup("SLIMBUS_0_TX"); my_data->max_mic_count = PLATFORM_DEFAULT_MIC_COUNT; my_data->max_mic_count = PLATFORM_DEFAULT_MIC_COUNT; } } Loading Loading @@ -2060,6 +2078,11 @@ int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type) return device_id; return device_id; } } int platform_get_haptics_pcm_device_id() { return HAPTICS_PCM_DEVICE; } static int find_index(const struct name_to_index * table, int32_t len, static int find_index(const struct name_to_index * table, int32_t len, const char * name) const char * name) { { Loading Loading @@ -2893,8 +2916,11 @@ snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devi snd_device = SND_DEVICE_OUT_VOICE_HANDSET_TMUS; snd_device = SND_DEVICE_OUT_VOICE_HANDSET_TMUS; else else snd_device = SND_DEVICE_OUT_VOICE_HANDSET; snd_device = SND_DEVICE_OUT_VOICE_HANDSET; } else if (devices & AUDIO_DEVICE_OUT_TELEPHONY_TX) } else if (devices & AUDIO_DEVICE_OUT_TELEPHONY_TX) { snd_device = SND_DEVICE_OUT_VOICE_TX; snd_device = SND_DEVICE_OUT_VOICE_TX; } else if (devices & AUDIO_DEVICE_OUT_HEARING_AID) { snd_device = SND_DEVICE_OUT_VOICE_HEARING_AID; } if (snd_device != SND_DEVICE_NONE) { if (snd_device != SND_DEVICE_NONE) { goto exit; goto exit; Loading Loading @@ -3186,6 +3212,8 @@ snd_device_t platform_get_input_snd_device(void *platform, snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC; snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC; } } } } } else if (out_device & AUDIO_DEVICE_OUT_HEARING_AID) { snd_device = SND_DEVICE_IN_VOICE_HEARING_AID; } } } else if (source == AUDIO_SOURCE_CAMCORDER) { } else if (source == AUDIO_SOURCE_CAMCORDER) { if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC || if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC || Loading Loading @@ -3702,6 +3730,7 @@ int64_t platform_render_latency(audio_usecase_t usecase) case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER: case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER: return DEEP_BUFFER_PLATFORM_DELAY; return DEEP_BUFFER_PLATFORM_DELAY; case USECASE_AUDIO_PLAYBACK_LOW_LATENCY: case USECASE_AUDIO_PLAYBACK_LOW_LATENCY: case USECASE_AUDIO_PLAYBACK_WITH_HAPTICS: return LOW_LATENCY_PLATFORM_DELAY; return LOW_LATENCY_PLATFORM_DELAY; case USECASE_AUDIO_PLAYBACK_ULL: case USECASE_AUDIO_PLAYBACK_ULL: return ULL_PLATFORM_DELAY; return ULL_PLATFORM_DELAY; Loading