Loading hal/Android.mk +5 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,11 @@ ifneq ($(strip $(AUDIO_FEATURE_DISABLED_PROXY_DEVICE)),true) LOCAL_CFLAGS += -DAFE_PROXY_ENABLED endif ifneq ($(strip $(AUDIO_FEATURE_DISABLED_FM)),true) LOCAL_CFLAGS += -DFM_ENABLED LOCAL_SRC_FILES += audio_extn/fm.c endif LOCAL_SHARED_LIBRARIES := \ liblog \ libcutils \ Loading hal/audio_extn/audio_extn.c +7 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,12 @@ static struct audio_extn_module aextnmod = { #define AUDIO_PARAMETER_KEY_ANC "anc_enabled" #define AUDIO_PARAMETER_KEY_WFD "wfd_channel_cap" #define AUDIO_PARAMETER_CAN_OPEN_PROXY "can_open_proxy" #ifndef FM_ENABLED #define audio_extn_fm_set_parameters(adev, parms) (0) #else void audio_extn_fm_set_parameters(struct audio_device *adev, struct str_parms *parms); #endif #ifndef ANC_HEADSET_ENABLED #define audio_extn_set_anc_parameters(parms) (0) Loading Loading @@ -180,6 +186,7 @@ void audio_extn_set_parameters(struct audio_device *adev, { audio_extn_set_anc_parameters(parms); audio_extn_set_afe_proxy_parameters(parms); audio_extn_fm_set_parameters(adev, parms); } char* audio_extn_get_parameters(const struct audio_hw_device *dev, Loading hal/audio_extn/fm.c 0 → 100644 +258 −0 Original line number Diff line number Diff line /* * Copyright (c) 2013, The Linux Foundation. All rights reserved. * Not a Contribution. * * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "audio_hw_fm" /*#define LOG_NDEBUG 0*/ #define LOG_NDDEBUG 0 #include <errno.h> #include <math.h> #include <cutils/log.h> #include "audio_hw.h" #include "platform.h" #include "platform_api.h" #include <stdlib.h> #include <cutils/str_parms.h> #ifdef FM_ENABLED #define AUDIO_PARAMETER_KEY_HANDLE_FM "handle_fm" #define AUDIO_PARAMETER_KEY_FM_VOLUME "fm_volume" static struct pcm_config pcm_config_fm = { .channels = 2, .rate = 48000, .period_size = 256, .period_count = 4, .format = PCM_FORMAT_S16_LE, .start_threshold = 0, .stop_threshold = INT_MAX, .avail_min = 0, }; struct fm_module { struct pcm *fm_pcm_rx; struct pcm *fm_pcm_tx; bool is_fm_running; int fm_volume; }; static struct fm_module fmmod = { .fm_pcm_rx = NULL, .fm_pcm_tx = NULL, .fm_volume = 0, .is_fm_running = 0, }; static int32_t fm_set_volume(struct audio_device *adev, float value) { int32_t vol, ret = 0; struct mixer_ctl *ctl; const char *mixer_ctl_name = "Internal FM RX Volume"; ALOGD("%s: entry", __func__); ALOGD("%s: (%f)\n", __func__, value); if (value < 0.0) { ALOGW("%s: (%f) Under 0.0, assuming 0.0\n", __func__, value); value = 0.0; } else if (value > 1.0) { ALOGW("%s: (%f) Over 1.0, assuming 1.0\n", __func__, value); value = 1.0; } vol = lrint((value * 0x2000) + 0.5); fmmod.fm_volume = vol; if (!fmmod.is_fm_running) { ALOGV("%s: FM not active, ignoring set_fm_volume call", __func__); return -EIO; } ALOGD("%s: Setting FM volume to %d \n", __func__, vol); ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name); if (!ctl) { ALOGE("%s: Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name); return -EINVAL; } mixer_ctl_set_value(ctl, 0, fmmod.fm_volume); ALOGD("%s: exit", __func__); return ret; } static int32_t fm_stop(struct audio_device *adev) { int32_t i, ret = 0; struct audio_usecase *uc_info; ALOGD("%s: enter", __func__); fmmod.is_fm_running = false; /* 1. Close the PCM devices */ if (fmmod.fm_pcm_rx) { pcm_close(fmmod.fm_pcm_rx); fmmod.fm_pcm_rx = NULL; } if (fmmod.fm_pcm_tx) { pcm_close(fmmod.fm_pcm_tx); fmmod.fm_pcm_tx = NULL; } uc_info = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_FM); if (uc_info == NULL) { ALOGE("%s: Could not find the usecase (%d) in the list", __func__, USECASE_VOICE_CALL); return -EINVAL; } /* 2. Get and set stream specific mixer controls */ disable_audio_route(adev, uc_info, true); /* 3. Disable the rx and tx devices */ disable_snd_device(adev, uc_info->out_snd_device, false); disable_snd_device(adev, uc_info->in_snd_device, true); list_remove(&uc_info->list); free(uc_info); ALOGD("%s: exit: status(%d)", __func__, ret); return ret; } static int32_t fm_start(struct audio_device *adev) { int32_t i, ret = 0; struct audio_usecase *uc_info; int32_t pcm_dev_rx_id, pcm_dev_tx_id; ALOGD("%s: enter", __func__); uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase)); uc_info->id = USECASE_AUDIO_PLAYBACK_FM; uc_info->type = PCM_PLAYBACK; uc_info->stream.out = adev->primary_output; uc_info->devices = adev->primary_output->devices; uc_info->in_snd_device = SND_DEVICE_NONE; uc_info->out_snd_device = SND_DEVICE_NONE; list_add_tail(&adev->usecase_list, &uc_info->list); select_devices(adev, USECASE_AUDIO_PLAYBACK_FM); pcm_dev_rx_id = platform_get_pcm_device_id(uc_info->id, PCM_PLAYBACK); pcm_dev_tx_id = platform_get_pcm_device_id(uc_info->id, PCM_CAPTURE); if (pcm_dev_rx_id < 0 || pcm_dev_tx_id < 0) { ALOGE("%s: Invalid PCM devices (rx: %d tx: %d) for the usecase(%d)", __func__, pcm_dev_rx_id, pcm_dev_tx_id, uc_info->id); ret = -EIO; goto exit; } ALOGV("%s: FM PCM devices (rx: %d tx: %d) for the usecase(%d)", __func__, pcm_dev_rx_id, pcm_dev_tx_id, uc_info->id); ALOGV("%s: Opening PCM playback device card_id(%d) device_id(%d)", __func__, SOUND_CARD, pcm_dev_rx_id); fmmod.fm_pcm_rx = pcm_open(SOUND_CARD, pcm_dev_rx_id, PCM_OUT, &pcm_config_fm); if (fmmod.fm_pcm_rx && !pcm_is_ready(fmmod.fm_pcm_rx)) { ALOGE("%s: %s", __func__, pcm_get_error(fmmod.fm_pcm_rx)); ret = -EIO; goto exit; } ALOGV("%s: Opening PCM capture device card_id(%d) device_id(%d)", __func__, SOUND_CARD, pcm_dev_tx_id); fmmod.fm_pcm_tx = pcm_open(SOUND_CARD, pcm_dev_tx_id, PCM_IN, &pcm_config_fm); if (fmmod.fm_pcm_tx && !pcm_is_ready(fmmod.fm_pcm_tx)) { ALOGE("%s: %s", __func__, pcm_get_error(fmmod.fm_pcm_tx)); ret = -EIO; goto exit; } pcm_start(fmmod.fm_pcm_rx); pcm_start(fmmod.fm_pcm_tx); fmmod.is_fm_running = true; fm_set_volume(adev, fmmod.fm_volume); ALOGD("%s: exit: status(%d)", __func__, ret); return 0; exit: fm_stop(adev); ALOGE("%s: Problem in FM start: status(%d)", __func__, ret); return ret; } void audio_extn_fm_set_parameters(struct audio_device *adev, struct str_parms *parms) { int ret, val; char value[32]={0}; float vol =0.0; ALOGV("%s: enter", __func__); if(fmmod.is_fm_running) { ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value)); if (ret >= 0) { val = atoi(value); if(val > 0) select_devices(adev, USECASE_AUDIO_PLAYBACK_FM); } } ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_HANDLE_FM, value, sizeof(value)); if (ret >= 0) { val = atoi(value); ALOGD("%s: FM usecase", __func__); if (val != 0) { if(val & AUDIO_DEVICE_OUT_FM && fmmod.is_fm_running == false) fm_start(adev); else if (!(val & AUDIO_DEVICE_OUT_FM) && fmmod.is_fm_running == true) fm_stop(adev); } } memset(value, 0, sizeof(value)); ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_FM_VOLUME, value, sizeof(value)); if (ret >= 0) { if (sscanf(value, "%f", &vol) != 1){ ALOGE("%s: error in retrieving fm volume", __func__); ret = -EIO; goto exit; } ALOGD("%s: set_fm_volume usecase", __func__); fm_set_volume(adev, vol); } exit: ALOGV("%s: exit", __func__); } #endif /* FM_ENABLED end */ hal/audio_hw.c +30 −9 Original line number Diff line number Diff line Loading @@ -94,6 +94,7 @@ static const char * const use_case_table[AUDIO_USECASE_MAX] = { [USECASE_AUDIO_RECORD] = "audio-record", [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record", [USECASE_VOICE_CALL] = "voice-call", [USECASE_AUDIO_PLAYBACK_FM] = "play-fm", }; Loading @@ -110,13 +111,16 @@ static const struct string_to_enum out_channels_name_to_enum_table[] = { STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1), }; static struct audio_device *adev = NULL; static pthread_mutex_t adev_init_lock; static bool is_adev_initialised = false; static int enable_audio_route(struct audio_device *adev, struct audio_usecase *usecase, bool update_mixer) { snd_device_t snd_device; char mixer_path[50]; char mixer_path[MIXER_PATH_MAX_LENGTH]; if (usecase == NULL) return -EINVAL; Loading @@ -139,12 +143,12 @@ static int enable_audio_route(struct audio_device *adev, return 0; } static int disable_audio_route(struct audio_device *adev, int disable_audio_route(struct audio_device *adev, struct audio_usecase *usecase, bool update_mixer) { snd_device_t snd_device; char mixer_path[50]; char mixer_path[MIXER_PATH_MAX_LENGTH]; if (usecase == NULL) return -EINVAL; Loading Loading @@ -196,7 +200,7 @@ static int enable_snd_device(struct audio_device *adev, return 0; } static int disable_snd_device(struct audio_device *adev, int disable_snd_device(struct audio_device *adev, snd_device_t snd_device, bool update_mixer) { Loading Loading @@ -384,7 +388,7 @@ static int read_hdmi_channel_masks(struct stream_out *out) return ret; } static struct audio_usecase *get_usecase_from_list(struct audio_device *adev, struct audio_usecase *get_usecase_from_list(struct audio_device *adev, audio_usecase_t uc_id) { struct audio_usecase *usecase; Loading @@ -398,7 +402,7 @@ static struct audio_usecase *get_usecase_from_list(struct audio_device *adev, return NULL; } static int select_devices(struct audio_device *adev, int select_devices(struct audio_device *adev, audio_usecase_t uc_id) { snd_device_t out_snd_device = SND_DEVICE_NONE; Loading Loading @@ -970,6 +974,13 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) pthread_mutex_unlock(&adev->lock); pthread_mutex_unlock(&out->lock); } if (out == adev->primary_output) { pthread_mutex_lock(&adev->lock); audio_extn_set_parameters(adev, parms); pthread_mutex_unlock(&adev->lock); } str_parms_destroy(parms); ALOGV("%s: exit: code(%d)", __func__, ret); return ret; Loading Loading @@ -1710,12 +1721,20 @@ static int adev_close(hw_device_t *device) static int adev_open(const hw_module_t *module, const char *name, hw_device_t **device) { struct audio_device *adev; int i, ret; ALOGD("%s: enter", __func__); if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL; pthread_mutex_lock(&adev_init_lock); if (is_adev_initialised == true){ *device = &adev->device.common; ALOGD("%s: returning existing instance of adev", __func__); ALOGD("%s: exit", __func__); pthread_mutex_unlock(&adev_init_lock); return 0; } adev = calloc(1, sizeof(struct audio_device)); adev->device.common.tag = HARDWARE_DEVICE_TAG; Loading @@ -1742,7 +1761,6 @@ static int adev_open(const hw_module_t *module, const char *name, adev->device.dump = adev_dump; /* Set the default route before the PCM stream is opened */ pthread_mutex_lock(&adev->lock); adev->mode = AUDIO_MODE_NORMAL; adev->active_input = NULL; adev->primary_output = NULL; Loading @@ -1756,7 +1774,6 @@ static int adev_open(const hw_module_t *module, const char *name, adev->acdb_settings = TTY_MODE_OFF; adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int)); list_init(&adev->usecase_list); pthread_mutex_unlock(&adev->lock); /* Loads platform specific libraries dynamically */ adev->platform = platform_init(adev); Loading @@ -1769,6 +1786,10 @@ static int adev_open(const hw_module_t *module, const char *name, } *device = &adev->device.common; /* update init flag*/ is_adev_initialised = true; pthread_mutex_unlock(&adev_init_lock); ALOGV("%s: exit", __func__); return 0; } Loading hal/audio_hw.h +12 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,8 @@ typedef enum { USECASE_AUDIO_PLAYBACK_DEEP_BUFFER = 0, USECASE_AUDIO_PLAYBACK_LOW_LATENCY, USECASE_AUDIO_PLAYBACK_MULTI_CH, /* FM usecase */ USECASE_AUDIO_PLAYBACK_FM, /* Capture usecases */ USECASE_AUDIO_RECORD, Loading Loading @@ -151,6 +153,16 @@ struct audio_device { void *platform; }; int select_devices(struct audio_device *adev, audio_usecase_t uc_id); int disable_audio_route(struct audio_device *adev, struct audio_usecase *usecase, bool update_mixer); int disable_snd_device(struct audio_device *adev, snd_device_t snd_device, bool update_mixer); struct audio_usecase *get_usecase_from_list(struct audio_device *adev, audio_usecase_t uc_id); /* * NOTE: when multiple mutexes have to be acquired, always take the * stream_in or stream_out mutex first, followed by the audio_device mutex. Loading Loading
hal/Android.mk +5 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,11 @@ ifneq ($(strip $(AUDIO_FEATURE_DISABLED_PROXY_DEVICE)),true) LOCAL_CFLAGS += -DAFE_PROXY_ENABLED endif ifneq ($(strip $(AUDIO_FEATURE_DISABLED_FM)),true) LOCAL_CFLAGS += -DFM_ENABLED LOCAL_SRC_FILES += audio_extn/fm.c endif LOCAL_SHARED_LIBRARIES := \ liblog \ libcutils \ Loading
hal/audio_extn/audio_extn.c +7 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,12 @@ static struct audio_extn_module aextnmod = { #define AUDIO_PARAMETER_KEY_ANC "anc_enabled" #define AUDIO_PARAMETER_KEY_WFD "wfd_channel_cap" #define AUDIO_PARAMETER_CAN_OPEN_PROXY "can_open_proxy" #ifndef FM_ENABLED #define audio_extn_fm_set_parameters(adev, parms) (0) #else void audio_extn_fm_set_parameters(struct audio_device *adev, struct str_parms *parms); #endif #ifndef ANC_HEADSET_ENABLED #define audio_extn_set_anc_parameters(parms) (0) Loading Loading @@ -180,6 +186,7 @@ void audio_extn_set_parameters(struct audio_device *adev, { audio_extn_set_anc_parameters(parms); audio_extn_set_afe_proxy_parameters(parms); audio_extn_fm_set_parameters(adev, parms); } char* audio_extn_get_parameters(const struct audio_hw_device *dev, Loading
hal/audio_extn/fm.c 0 → 100644 +258 −0 Original line number Diff line number Diff line /* * Copyright (c) 2013, The Linux Foundation. All rights reserved. * Not a Contribution. * * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "audio_hw_fm" /*#define LOG_NDEBUG 0*/ #define LOG_NDDEBUG 0 #include <errno.h> #include <math.h> #include <cutils/log.h> #include "audio_hw.h" #include "platform.h" #include "platform_api.h" #include <stdlib.h> #include <cutils/str_parms.h> #ifdef FM_ENABLED #define AUDIO_PARAMETER_KEY_HANDLE_FM "handle_fm" #define AUDIO_PARAMETER_KEY_FM_VOLUME "fm_volume" static struct pcm_config pcm_config_fm = { .channels = 2, .rate = 48000, .period_size = 256, .period_count = 4, .format = PCM_FORMAT_S16_LE, .start_threshold = 0, .stop_threshold = INT_MAX, .avail_min = 0, }; struct fm_module { struct pcm *fm_pcm_rx; struct pcm *fm_pcm_tx; bool is_fm_running; int fm_volume; }; static struct fm_module fmmod = { .fm_pcm_rx = NULL, .fm_pcm_tx = NULL, .fm_volume = 0, .is_fm_running = 0, }; static int32_t fm_set_volume(struct audio_device *adev, float value) { int32_t vol, ret = 0; struct mixer_ctl *ctl; const char *mixer_ctl_name = "Internal FM RX Volume"; ALOGD("%s: entry", __func__); ALOGD("%s: (%f)\n", __func__, value); if (value < 0.0) { ALOGW("%s: (%f) Under 0.0, assuming 0.0\n", __func__, value); value = 0.0; } else if (value > 1.0) { ALOGW("%s: (%f) Over 1.0, assuming 1.0\n", __func__, value); value = 1.0; } vol = lrint((value * 0x2000) + 0.5); fmmod.fm_volume = vol; if (!fmmod.is_fm_running) { ALOGV("%s: FM not active, ignoring set_fm_volume call", __func__); return -EIO; } ALOGD("%s: Setting FM volume to %d \n", __func__, vol); ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name); if (!ctl) { ALOGE("%s: Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name); return -EINVAL; } mixer_ctl_set_value(ctl, 0, fmmod.fm_volume); ALOGD("%s: exit", __func__); return ret; } static int32_t fm_stop(struct audio_device *adev) { int32_t i, ret = 0; struct audio_usecase *uc_info; ALOGD("%s: enter", __func__); fmmod.is_fm_running = false; /* 1. Close the PCM devices */ if (fmmod.fm_pcm_rx) { pcm_close(fmmod.fm_pcm_rx); fmmod.fm_pcm_rx = NULL; } if (fmmod.fm_pcm_tx) { pcm_close(fmmod.fm_pcm_tx); fmmod.fm_pcm_tx = NULL; } uc_info = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_FM); if (uc_info == NULL) { ALOGE("%s: Could not find the usecase (%d) in the list", __func__, USECASE_VOICE_CALL); return -EINVAL; } /* 2. Get and set stream specific mixer controls */ disable_audio_route(adev, uc_info, true); /* 3. Disable the rx and tx devices */ disable_snd_device(adev, uc_info->out_snd_device, false); disable_snd_device(adev, uc_info->in_snd_device, true); list_remove(&uc_info->list); free(uc_info); ALOGD("%s: exit: status(%d)", __func__, ret); return ret; } static int32_t fm_start(struct audio_device *adev) { int32_t i, ret = 0; struct audio_usecase *uc_info; int32_t pcm_dev_rx_id, pcm_dev_tx_id; ALOGD("%s: enter", __func__); uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase)); uc_info->id = USECASE_AUDIO_PLAYBACK_FM; uc_info->type = PCM_PLAYBACK; uc_info->stream.out = adev->primary_output; uc_info->devices = adev->primary_output->devices; uc_info->in_snd_device = SND_DEVICE_NONE; uc_info->out_snd_device = SND_DEVICE_NONE; list_add_tail(&adev->usecase_list, &uc_info->list); select_devices(adev, USECASE_AUDIO_PLAYBACK_FM); pcm_dev_rx_id = platform_get_pcm_device_id(uc_info->id, PCM_PLAYBACK); pcm_dev_tx_id = platform_get_pcm_device_id(uc_info->id, PCM_CAPTURE); if (pcm_dev_rx_id < 0 || pcm_dev_tx_id < 0) { ALOGE("%s: Invalid PCM devices (rx: %d tx: %d) for the usecase(%d)", __func__, pcm_dev_rx_id, pcm_dev_tx_id, uc_info->id); ret = -EIO; goto exit; } ALOGV("%s: FM PCM devices (rx: %d tx: %d) for the usecase(%d)", __func__, pcm_dev_rx_id, pcm_dev_tx_id, uc_info->id); ALOGV("%s: Opening PCM playback device card_id(%d) device_id(%d)", __func__, SOUND_CARD, pcm_dev_rx_id); fmmod.fm_pcm_rx = pcm_open(SOUND_CARD, pcm_dev_rx_id, PCM_OUT, &pcm_config_fm); if (fmmod.fm_pcm_rx && !pcm_is_ready(fmmod.fm_pcm_rx)) { ALOGE("%s: %s", __func__, pcm_get_error(fmmod.fm_pcm_rx)); ret = -EIO; goto exit; } ALOGV("%s: Opening PCM capture device card_id(%d) device_id(%d)", __func__, SOUND_CARD, pcm_dev_tx_id); fmmod.fm_pcm_tx = pcm_open(SOUND_CARD, pcm_dev_tx_id, PCM_IN, &pcm_config_fm); if (fmmod.fm_pcm_tx && !pcm_is_ready(fmmod.fm_pcm_tx)) { ALOGE("%s: %s", __func__, pcm_get_error(fmmod.fm_pcm_tx)); ret = -EIO; goto exit; } pcm_start(fmmod.fm_pcm_rx); pcm_start(fmmod.fm_pcm_tx); fmmod.is_fm_running = true; fm_set_volume(adev, fmmod.fm_volume); ALOGD("%s: exit: status(%d)", __func__, ret); return 0; exit: fm_stop(adev); ALOGE("%s: Problem in FM start: status(%d)", __func__, ret); return ret; } void audio_extn_fm_set_parameters(struct audio_device *adev, struct str_parms *parms) { int ret, val; char value[32]={0}; float vol =0.0; ALOGV("%s: enter", __func__); if(fmmod.is_fm_running) { ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value)); if (ret >= 0) { val = atoi(value); if(val > 0) select_devices(adev, USECASE_AUDIO_PLAYBACK_FM); } } ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_HANDLE_FM, value, sizeof(value)); if (ret >= 0) { val = atoi(value); ALOGD("%s: FM usecase", __func__); if (val != 0) { if(val & AUDIO_DEVICE_OUT_FM && fmmod.is_fm_running == false) fm_start(adev); else if (!(val & AUDIO_DEVICE_OUT_FM) && fmmod.is_fm_running == true) fm_stop(adev); } } memset(value, 0, sizeof(value)); ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_FM_VOLUME, value, sizeof(value)); if (ret >= 0) { if (sscanf(value, "%f", &vol) != 1){ ALOGE("%s: error in retrieving fm volume", __func__); ret = -EIO; goto exit; } ALOGD("%s: set_fm_volume usecase", __func__); fm_set_volume(adev, vol); } exit: ALOGV("%s: exit", __func__); } #endif /* FM_ENABLED end */
hal/audio_hw.c +30 −9 Original line number Diff line number Diff line Loading @@ -94,6 +94,7 @@ static const char * const use_case_table[AUDIO_USECASE_MAX] = { [USECASE_AUDIO_RECORD] = "audio-record", [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record", [USECASE_VOICE_CALL] = "voice-call", [USECASE_AUDIO_PLAYBACK_FM] = "play-fm", }; Loading @@ -110,13 +111,16 @@ static const struct string_to_enum out_channels_name_to_enum_table[] = { STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1), }; static struct audio_device *adev = NULL; static pthread_mutex_t adev_init_lock; static bool is_adev_initialised = false; static int enable_audio_route(struct audio_device *adev, struct audio_usecase *usecase, bool update_mixer) { snd_device_t snd_device; char mixer_path[50]; char mixer_path[MIXER_PATH_MAX_LENGTH]; if (usecase == NULL) return -EINVAL; Loading @@ -139,12 +143,12 @@ static int enable_audio_route(struct audio_device *adev, return 0; } static int disable_audio_route(struct audio_device *adev, int disable_audio_route(struct audio_device *adev, struct audio_usecase *usecase, bool update_mixer) { snd_device_t snd_device; char mixer_path[50]; char mixer_path[MIXER_PATH_MAX_LENGTH]; if (usecase == NULL) return -EINVAL; Loading Loading @@ -196,7 +200,7 @@ static int enable_snd_device(struct audio_device *adev, return 0; } static int disable_snd_device(struct audio_device *adev, int disable_snd_device(struct audio_device *adev, snd_device_t snd_device, bool update_mixer) { Loading Loading @@ -384,7 +388,7 @@ static int read_hdmi_channel_masks(struct stream_out *out) return ret; } static struct audio_usecase *get_usecase_from_list(struct audio_device *adev, struct audio_usecase *get_usecase_from_list(struct audio_device *adev, audio_usecase_t uc_id) { struct audio_usecase *usecase; Loading @@ -398,7 +402,7 @@ static struct audio_usecase *get_usecase_from_list(struct audio_device *adev, return NULL; } static int select_devices(struct audio_device *adev, int select_devices(struct audio_device *adev, audio_usecase_t uc_id) { snd_device_t out_snd_device = SND_DEVICE_NONE; Loading Loading @@ -970,6 +974,13 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) pthread_mutex_unlock(&adev->lock); pthread_mutex_unlock(&out->lock); } if (out == adev->primary_output) { pthread_mutex_lock(&adev->lock); audio_extn_set_parameters(adev, parms); pthread_mutex_unlock(&adev->lock); } str_parms_destroy(parms); ALOGV("%s: exit: code(%d)", __func__, ret); return ret; Loading Loading @@ -1710,12 +1721,20 @@ static int adev_close(hw_device_t *device) static int adev_open(const hw_module_t *module, const char *name, hw_device_t **device) { struct audio_device *adev; int i, ret; ALOGD("%s: enter", __func__); if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL; pthread_mutex_lock(&adev_init_lock); if (is_adev_initialised == true){ *device = &adev->device.common; ALOGD("%s: returning existing instance of adev", __func__); ALOGD("%s: exit", __func__); pthread_mutex_unlock(&adev_init_lock); return 0; } adev = calloc(1, sizeof(struct audio_device)); adev->device.common.tag = HARDWARE_DEVICE_TAG; Loading @@ -1742,7 +1761,6 @@ static int adev_open(const hw_module_t *module, const char *name, adev->device.dump = adev_dump; /* Set the default route before the PCM stream is opened */ pthread_mutex_lock(&adev->lock); adev->mode = AUDIO_MODE_NORMAL; adev->active_input = NULL; adev->primary_output = NULL; Loading @@ -1756,7 +1774,6 @@ static int adev_open(const hw_module_t *module, const char *name, adev->acdb_settings = TTY_MODE_OFF; adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int)); list_init(&adev->usecase_list); pthread_mutex_unlock(&adev->lock); /* Loads platform specific libraries dynamically */ adev->platform = platform_init(adev); Loading @@ -1769,6 +1786,10 @@ static int adev_open(const hw_module_t *module, const char *name, } *device = &adev->device.common; /* update init flag*/ is_adev_initialised = true; pthread_mutex_unlock(&adev_init_lock); ALOGV("%s: exit", __func__); return 0; } Loading
hal/audio_hw.h +12 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,8 @@ typedef enum { USECASE_AUDIO_PLAYBACK_DEEP_BUFFER = 0, USECASE_AUDIO_PLAYBACK_LOW_LATENCY, USECASE_AUDIO_PLAYBACK_MULTI_CH, /* FM usecase */ USECASE_AUDIO_PLAYBACK_FM, /* Capture usecases */ USECASE_AUDIO_RECORD, Loading Loading @@ -151,6 +153,16 @@ struct audio_device { void *platform; }; int select_devices(struct audio_device *adev, audio_usecase_t uc_id); int disable_audio_route(struct audio_device *adev, struct audio_usecase *usecase, bool update_mixer); int disable_snd_device(struct audio_device *adev, snd_device_t snd_device, bool update_mixer); struct audio_usecase *get_usecase_from_list(struct audio_device *adev, audio_usecase_t uc_id); /* * NOTE: when multiple mutexes have to be acquired, always take the * stream_in or stream_out mutex first, followed by the audio_device mutex. Loading