diff options
author | Sangchul Lee <sc11.lee@samsung.com> | 2016-06-08 10:54:15 +0900 |
---|---|---|
committer | Sangchul Lee <sc11.lee@samsung.com> | 2016-06-08 15:09:56 +0900 |
commit | a712aa1320feb49e9f2a862afa53ea79f564e9a0 (patch) | |
tree | 569d233349d5e4a354e3e9c3a96c950f588d7ed2 | |
parent | f34bfc637ad6652b24a75da389c36691fda49025 (diff) | |
download | audio-hal-sc7727-a712aa1320feb49e9f2a862afa53ea79f564e9a0.tar.gz audio-hal-sc7727-a712aa1320feb49e9f2a862afa53ea79f564e9a0.tar.bz2 audio-hal-sc7727-a712aa1320feb49e9f2a862afa53ea79f564e9a0.zip |
Add support for radiosubmit/tizen/20160608.063231accepted/tizen/mobile/20160608.084539
[Version] 0.1.11
[Profile] Mobile
[Issue Type] Feature Enhancement
Change-Id: I1ac916a95a2b3dceeb4243a4b6f41e6d0feccc41
Signed-off-by: Sangchul Lee <sc11.lee@samsung.com>
-rw-r--r-- | packaging/audio-hal-sc7727.spec | 2 | ||||
-rw-r--r-- | tizen-audio-impl-pcm.c | 128 | ||||
-rw-r--r-- | tizen-audio-impl-ucm.c | 18 | ||||
-rw-r--r-- | tizen-audio-impl.h | 26 | ||||
-rw-r--r-- | tizen-audio-internal.h | 10 | ||||
-rw-r--r-- | tizen-audio-modem.c | 45 | ||||
-rw-r--r-- | tizen-audio-pcm.c | 1 | ||||
-rw-r--r-- | tizen-audio-routing.c | 112 | ||||
-rw-r--r-- | tizen-audio-stream.c | 7 | ||||
-rw-r--r-- | tizen-audio-volume.c | 147 |
10 files changed, 399 insertions, 97 deletions
diff --git a/packaging/audio-hal-sc7727.spec b/packaging/audio-hal-sc7727.spec index 4bb1fe2..9adb3dc 100644 --- a/packaging/audio-hal-sc7727.spec +++ b/packaging/audio-hal-sc7727.spec @@ -1,6 +1,6 @@ Name: audio-hal-sc7727 Summary: TIZEN Audio HAL for SC7727 -Version: 0.1.10 +Version: 0.1.11 Release: 0 Group: System/Libraries License: Apache-2.0 diff --git a/tizen-audio-impl-pcm.c b/tizen-audio-impl-pcm.c index a478143..efb62fc 100644 --- a/tizen-audio-impl-pcm.c +++ b/tizen-audio-impl-pcm.c @@ -183,16 +183,83 @@ static int __tinyalsa_pcm_recover(struct pcm *pcm, int err) } #endif -int _voice_pcm_open(audio_hal_t *ah) +audio_return_t _fmradio_pcm_open(audio_hal_t *ah) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + int ret = 0; + const char *device_name = NULL; + audio_pcm_sample_spec_t sample_spec; + uint8_t use_mmap = 0; + sample_spec.rate = 44100; + sample_spec.channels = 2; + sample_spec.format = SND_PCM_FORMAT_S16_LE; + + if ((audio_ret = _ucm_get_device_name(ah, AUDIO_USE_CASE_VERB_FMRADIO, AUDIO_DIRECTION_OUT, &device_name))) + goto error_exit; + +#ifdef __USE_TINYALSA__ + AUDIO_LOG_WARN("need implementation for tinyAlsa"); + return AUDIO_ERR_NOT_IMPLEMENTED; +#else + if (device_name) { + if((ret = snd_pcm_open((snd_pcm_t **)&ah->device.fmradio_pcm_out, (char *)device_name, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { + AUDIO_LOG_ERROR("[%s] out pcm_open failed", device_name); + audio_ret = AUDIO_ERR_IOCTL; + goto error_exit; + } + AUDIO_LOG_INFO("[%s] out pcm_open success:%p", device_name, ah->device.fmradio_pcm_out); + + if ((audio_ret = _pcm_set_hw_params(ah->device.fmradio_pcm_out, &sample_spec, &use_mmap, NULL, NULL)) < 0) { + AUDIO_LOG_ERROR("[%s] out __set_pcm_hw_params failed", device_name); + if ((audio_ret = _pcm_close(ah->device.pcm_out))) + AUDIO_LOG_ERROR("failed to _pcm_close(), ret(0x%x)", audio_ret); + ah->device.fmradio_pcm_out = NULL; + goto error_exit; + } + } +#endif + +error_exit: + if (device_name) + free((void*)device_name); + + return audio_ret; +} + +audio_return_t _fmradio_pcm_close(audio_hal_t *ah) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + + AUDIO_LOG_INFO("close fmradio pcm handles"); + + if (ah->device.fmradio_pcm_out) { + if ((audio_ret = _pcm_close(ah->device.fmradio_pcm_out))) + AUDIO_LOG_ERROR("failed to _fmradio_pcm_close() for pcm_out, ret(0x%x)", audio_ret); + else { + ah->device.fmradio_pcm_out = NULL; + AUDIO_LOG_INFO("fmradio pcm_out handle close success"); + } + } + + return audio_ret; +} + +audio_return_t _voice_pcm_open(audio_hal_t *ah) { int err, ret = 0; AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); +#ifdef __USE_TINYALSA__ + AUDIO_LOG_WARN("need implementation for tinyAlsa"); + return AUDIO_ERR_NOT_IMPLEMENTED; +#else AUDIO_LOG_INFO("open voice pcm handles"); /* Get playback voice-pcm from ucm conf. Open and set-params */ - if ((err = snd_pcm_open((snd_pcm_t **)&ah->device.pcm_out, VOICE_PCM_DEVICE, AUDIO_DIRECTION_OUT, 0)) < 0) { + if ((err = snd_pcm_open((snd_pcm_t **)&ah->device.pcm_out, VOICE_PCM_DEVICE, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { AUDIO_LOG_ERROR("snd_pcm_open for %s failed. %s", VOICE_PCM_DEVICE, snd_strerror(err)); return AUDIO_ERR_IOCTL; } @@ -201,51 +268,70 @@ int _voice_pcm_open(audio_hal_t *ah) AUDIO_LOG_INFO("pcm playback device open success device(%s)", VOICE_PCM_DEVICE); /* Get capture voice-pcm from ucm conf. Open and set-params */ - if ((err = snd_pcm_open((snd_pcm_t **)&ah->device.pcm_in, VOICE_PCM_DEVICE, AUDIO_DIRECTION_IN, 0)) < 0) { + if ((err = snd_pcm_open((snd_pcm_t **)&ah->device.pcm_in, VOICE_PCM_DEVICE, SND_PCM_STREAM_CAPTURE, 0)) < 0) { AUDIO_LOG_ERROR("snd_pcm_open for %s failed. %s", VOICE_PCM_DEVICE, snd_strerror(err)); return AUDIO_ERR_IOCTL; } ret = __voice_pcm_set_params(ah, ah->device.pcm_in); AUDIO_LOG_INFO("pcm captures device open success device(%s)", VOICE_PCM_DEVICE); +#endif - return ret; + return (ret == 0 ? AUDIO_RET_OK : AUDIO_ERR_INTERNAL); } -int _voice_pcm_close(audio_hal_t *ah, uint32_t direction) +audio_return_t _voice_pcm_close(audio_hal_t *ah, uint32_t direction) { + audio_return_t audio_ret = AUDIO_RET_OK; + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); AUDIO_LOG_INFO("close voice pcm handles"); if (ah->device.pcm_out && (direction == AUDIO_DIRECTION_OUT)) { - _pcm_close(ah->device.pcm_out); - ah->device.pcm_out = NULL; - AUDIO_LOG_INFO("voice pcm_out handle close success"); + if ((audio_ret = _pcm_close(ah->device.pcm_out))) + AUDIO_LOG_ERROR("failed to _pcm_close() for pcm_out, ret(0x%x)", audio_ret); + else { + ah->device.pcm_out = NULL; + AUDIO_LOG_INFO("voice pcm_out handle close success"); + } } else if (ah->device.pcm_in && (direction == AUDIO_DIRECTION_IN)) { - _pcm_close(ah->device.pcm_in); - ah->device.pcm_in = NULL; - AUDIO_LOG_INFO("voice pcm_in handle close success"); + if ((audio_ret = _pcm_close(ah->device.pcm_in))) + AUDIO_LOG_ERROR("failed to _pcm_close() for pcm_in, ret(0x%x)", audio_ret); + else { + ah->device.pcm_in = NULL; + AUDIO_LOG_INFO("voice pcm_in handle close success"); + } } - return AUDIO_RET_OK; + return audio_ret; } -void _reset_pcm_devices(audio_hal_t *ah) +audio_return_t _reset_pcm_devices(audio_hal_t *ah) { - AUDIO_RETURN_IF_FAIL(ah); + audio_return_t audio_ret = AUDIO_RET_OK; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); if (ah->device.pcm_out) { - _pcm_close(ah->device.pcm_out); - ah->device.pcm_out = NULL; - AUDIO_LOG_INFO("pcm_out handle close success"); + if (!(audio_ret = _pcm_close(ah->device.pcm_out))) { + ah->device.pcm_out = NULL; + AUDIO_LOG_INFO("pcm_out handle close success"); + } } if (ah->device.pcm_in) { - _pcm_close(ah->device.pcm_in); - ah->device.pcm_in = NULL; - AUDIO_LOG_INFO("pcm_in handle close success"); + if (!(audio_ret = _pcm_close(ah->device.pcm_in))) { + ah->device.pcm_in = NULL; + AUDIO_LOG_INFO("pcm_in handle close success"); + } + } + if (ah->device.fmradio_pcm_out) { + if (!(audio_ret = _pcm_close(ah->device.fmradio_pcm_out))) { + ah->device.fmradio_pcm_out = NULL; + AUDIO_LOG_INFO("fmradio_pcm_out handle close success"); + } } - return; + return audio_ret; } audio_return_t _pcm_open(void **pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods) diff --git a/tizen-audio-impl-ucm.c b/tizen-audio-impl-ucm.c index 1dfe50a..23ce1a0 100644 --- a/tizen-audio-impl-ucm.c +++ b/tizen-audio-impl-ucm.c @@ -122,6 +122,24 @@ audio_return_t _ucm_deinit(audio_hal_t *ah) return AUDIO_RET_OK; } +audio_return_t _ucm_get_device_name(audio_hal_t *ah, const char *use_case, audio_direction_t direction, const char **value) +{ + char identifier[70] = { 0, }; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(use_case, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, AUDIO_ERR_PARAMETER); + + snprintf(identifier, sizeof(identifier), "%sPCM//%s", + (direction == AUDIO_DIRECTION_IN) ? "Capture" : "Playback", use_case); + + snd_use_case_get(ah->ucm.uc_mgr, identifier, value); + + AUDIO_LOG_INFO("get device name : [%s]", *value); + + return AUDIO_RET_OK; +} + /* UCM sequence 1) If verb is null or verb is not changed 1-1) If device is changed diff --git a/tizen-audio-impl.h b/tizen-audio-impl.h index 4410541..26a54a5 100644 --- a/tizen-audio-impl.h +++ b/tizen-audio-impl.h @@ -21,9 +21,11 @@ */ /* PCM */ -int _voice_pcm_open(audio_hal_t *ah); -int _voice_pcm_close(audio_hal_t *ah, uint32_t direction); -void _reset_pcm_devices(audio_hal_t *ah); +audio_return_t _fmradio_pcm_open(audio_hal_t *ah); +audio_return_t _fmradio_pcm_close(audio_hal_t *ah); +audio_return_t _voice_pcm_open(audio_hal_t *ah); +audio_return_t _voice_pcm_close(audio_hal_t *ah, uint32_t direction); +audio_return_t _reset_pcm_devices(audio_hal_t *ah); audio_return_t _pcm_open(void **pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods); audio_return_t _pcm_start(void *pcm_handle); audio_return_t _pcm_stop(void *pcm_handle); @@ -39,6 +41,23 @@ audio_return_t _pcm_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, u audio_return_t _pcm_set_hw_params(snd_pcm_t *pcm, audio_pcm_sample_spec_t *sample_spec, uint8_t *use_mmap, snd_pcm_uframes_t *period_size, snd_pcm_uframes_t *buffer_size); /* Control */ +#define VBC_TD_CHANNELID 0 /* cp [3g] */ +#define VBC_ARM_CHANNELID 2 /* ap */ +#define MIXER_VBC_SWITCH "VBC Switch" +#define PIN_SWITCH_IIS0_SYS_SEL "IIS0 pin select" +#define PIN_SWITCH_IIS0_AP_ID 0 +#define PIN_SWITCH_IIS0_CP0_ID 1 +#define PIN_SWITCH_IIS0_CP1_ID 2 +#define PIN_SWITCH_IIS0_CP2_ID 3 +#define PIN_SWITCH_IIS0_VBC_ID 4 +#define PIN_SWITCH_BT_IIS_SYS_SEL "BT IIS pin select" +#define PIN_SWITCH_BT_IIS_CP0_IIS0_ID 0 +#define PIN_SWITCH_BT_IIS_CP1_IIS0_ID 4 +#define PIN_SWITCH_BT_IIS_AP_IIS0_ID 8 +#define PIN_SWITCH_BT_IIS_CON_SWITCH "BT IIS con switch" +#define MIXER_FMRADIO_L_VOLUME "VBC STR DG Set" +#define MIXER_FMRADIO_R_VOLUME "VBC STL DG Set" +#define MIXER_FMRADIO_MUTE "Digital FM Function" audio_return_t _control_init(audio_hal_t *ah); audio_return_t _control_deinit(audio_hal_t *ah); audio_return_t _mixer_control_set_param(audio_hal_t *ah, const char* ctl_name, snd_ctl_elem_value_t* value, int size); @@ -50,6 +69,7 @@ audio_return_t _mixer_control_get_element(audio_hal_t *ah, const char *ctl_name, /* UCM */ audio_return_t _ucm_init(audio_hal_t *ah); audio_return_t _ucm_deinit(audio_hal_t *ah); +audio_return_t _ucm_get_device_name(audio_hal_t *ah, const char *use_case, audio_direction_t direction, const char **value); #define _ucm_update_use_case _ucm_set_use_case audio_return_t _ucm_set_use_case(audio_hal_t *ah, const char *verb, const char *devices[], const char *modifiers[]); audio_return_t _ucm_set_devices(audio_hal_t *ah, const char *verb, const char *devices[]); diff --git a/tizen-audio-internal.h b/tizen-audio-internal.h index e9f0647..2b44f37 100644 --- a/tizen-audio-internal.h +++ b/tizen-audio-internal.h @@ -143,7 +143,7 @@ typedef struct device_type { #define AUDIO_USE_CASE_VERB_VOICECALL "Voice" #define AUDIO_USE_CASE_VERB_VIDEOCALL "Video" #define AUDIO_USE_CASE_VERB_VOIP "VoIP" -#define AUDIO_USE_CASE_VERB_LOOPBACK "Loopback" +#define AUDIO_USE_CASE_VERB_FMRADIO "DigitalFM" /* Modifiers */ #define AUDIO_USE_CASE_MODIFIER_VOICESEARCH "VoiceSearch" @@ -183,7 +183,8 @@ typedef enum audio_route_mode { VERB_NORMAL, VERB_VOICECALL, VERB_VIDEOCALL, - VERB_VOIP + VERB_VOIP, + VERB_RADIO } audio_route_mode_t; typedef struct audio_hal_device { @@ -191,17 +192,20 @@ typedef struct audio_hal_device { uint32_t active_out; snd_pcm_t *pcm_in; snd_pcm_t *pcm_out; + snd_pcm_t *fmradio_pcm_out; pthread_mutex_t pcm_lock; uint32_t pcm_count; device_info_t *init_call_devices; uint32_t num_of_call_devices; audio_route_mode_t mode; + uint32_t is_radio_on; pthread_cond_t device_cond; pthread_mutex_t device_lock; } audio_hal_device_t; /* Volume */ #define AUDIO_VOLUME_LEVEL_MAX 16 +#define RADIO_VOLUME_MAX 16 typedef enum audio_volume { AUDIO_VOLUME_TYPE_SYSTEM, /**< System volume type */ @@ -244,6 +248,7 @@ enum { typedef struct audio_hal_volume { uint32_t volume_level[AUDIO_VOLUME_TYPE_MAX]; audio_volume_value_table_t *volume_value_table; + int32_t radio_volume_value_table[RADIO_VOLUME_MAX]; } audio_hal_volume_t; /* UCM */ @@ -337,6 +342,7 @@ audio_return_t _audio_comm_deinit(audio_hal_t *ah); audio_return_t _audio_update_route_voicecall(audio_hal_t *ah, device_info_t *devices, int32_t num_of_devices); int _audio_modem_is_call_connected(audio_hal_t *ah); audio_return_t _audio_comm_send_message(audio_hal_t *ah, const char *name, int value); +audio_return_t _audio_volume_set_level_radio(audio_hal_t *ah, uint32_t level); typedef struct _dump_data { char *strbuf; diff --git a/tizen-audio-modem.c b/tizen-audio-modem.c index 9ad85a7..31b5d2a 100644 --- a/tizen-audio-modem.c +++ b/tizen-audio-modem.c @@ -34,25 +34,6 @@ #include "tizen-audio-impl.h" #define vbc_thread_new pthread_create -#define MIXER_VBC_SWITCH "VBC Switch" -/* pin_switch */ -#define PIN_SWITCH_IIS0_SYS_SEL "IIS0 pin select" -#define PIN_SWITCH_IIS0_AP_ID 0 -#define PIN_SWITCH_IIS0_CP0_ID 1 -#define PIN_SWITCH_IIS0_CP1_ID 2 -#define PIN_SWITCH_IIS0_CP2_ID 3 -#define PIN_SWITCH_IIS0_VBC_ID 4 - -#define PIN_SWITCH_BT_IIS_SYS_SEL "BT IIS pin select" -#define PIN_SWITCH_BT_IIS_CP0_IIS0_ID 0 -#define PIN_SWITCH_BT_IIS_CP1_IIS0_ID 4 -#define PIN_SWITCH_BT_IIS_AP_IIS0_ID 8 - -#define PIN_SWITCH_BT_IIS_CON_SWITCH "BT IIS con switch" - -#define VBC_TD_CHANNELID 0 /* cp [3g] */ -#define VBC_ARM_CHANNELID 2 /* ap */ - #define VBPIPE_DEVICE "/dev/spipe_w6" #define VBPIPE_VOIP_DEVICE "/dev/spipe_w4" #define VBC_CMD_TAG "VBC" @@ -173,16 +154,6 @@ static int __write_nonblock(int fd, void *buf, int bytes) } -int _audio_modem_is_call_connected(audio_hal_t *ah) -{ - int val = -1; /* Mixer values 0 - cp [3g] ,1 - cp [2g] ,2 - ap */ - - _mixer_control_get_value(ah, MIXER_VBC_SWITCH, &val); - AUDIO_LOG_INFO("modem is connected for call = %d", (val == VBC_TD_CHANNELID)); - - return (val == VBC_TD_CHANNELID) ? 1 : 0; -} - static int __vbc_write_response(int fd, unsigned int cmd, uint32_t paras_size) { int ret = 0; @@ -202,7 +173,16 @@ static int __vbc_write_response(int fd, unsigned int cmd, uint32_t paras_size) return 0; } -#define FM_IIS 0x10 +int _audio_modem_is_call_connected(audio_hal_t *ah) +{ + int val = -1; /* Mixer values 0 - cp [3g] ,1 - cp [2g] ,2 - ap */ + + _mixer_control_get_value(ah, MIXER_VBC_SWITCH, &val); + AUDIO_LOG_INFO("modem is connected for call = %d", (val == VBC_TD_CHANNELID)); + + return (val == VBC_TD_CHANNELID) ? 1 : 0; +} + static void __i2s_pin_mux_sel(audio_hal_t *ah, int type) { audio_return_t ret = AUDIO_RET_OK; @@ -216,11 +196,6 @@ static void __i2s_pin_mux_sel(audio_hal_t *ah, int type) AUDIO_LOG_INFO("type is %d",type); modem = ah->modem.cp; - if (type == FM_IIS) { - _mixer_control_set_value(ah, - PIN_SWITCH_IIS0_SYS_SEL, PIN_SWITCH_IIS0_VBC_ID); - return; - } if (type == 0) { if(ah->device.active_out & AUDIO_DEVICE_OUT_BT_SCO) { if(modem->i2s_bt.is_ext) { diff --git a/tizen-audio-pcm.c b/tizen-audio-pcm.c index 08dc5ab..de97595 100644 --- a/tizen-audio-pcm.c +++ b/tizen-audio-pcm.c @@ -30,6 +30,7 @@ audio_return_t _audio_pcm_init(audio_hal_t *ah) ah->device.pcm_in = NULL; ah->device.pcm_out = NULL; + ah->device.fmradio_pcm_out = NULL; pthread_mutex_init(&ah->device.pcm_lock, NULL); pthread_mutex_init(&ah->device.device_lock, NULL); pthread_cond_init(&ah->device.device_cond, NULL); diff --git a/tizen-audio-routing.c b/tizen-audio-routing.c index c2d03ea..ce0971e 100644 --- a/tizen-audio-routing.c +++ b/tizen-audio-routing.c @@ -52,6 +52,7 @@ static const char* mode_to_verb_str[] = { AUDIO_USE_CASE_VERB_VOICECALL, AUDIO_USE_CASE_VERB_VIDEOCALL, AUDIO_USE_CASE_VERB_VOIP, + AUDIO_USE_CASE_VERB_FMRADIO, }; static uint32_t __convert_device_string_to_enum(const char* device_str, uint32_t direction) @@ -162,33 +163,51 @@ static audio_return_t __set_devices(audio_hal_t *ah, const char *verb, device_in return audio_ret; } +static audio_return_t __connect_fm_radio(audio_hal_t *ah) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + + audio_ret = _mixer_control_set_value(ah, + PIN_SWITCH_IIS0_SYS_SEL, PIN_SWITCH_IIS0_VBC_ID); + return audio_ret; +} + static audio_return_t __update_route_ap_playback_capture(audio_hal_t *ah, audio_route_info_t *route_info) { audio_return_t audio_ret = AUDIO_RET_OK; device_info_t *devices = NULL; const char *verb = mode_to_verb_str[VERB_NORMAL]; -#if 0 /* Disable setting modifiers, because driver does not support it yet */ - int mod_idx = 0; - const char *modifiers[MAX_MODIFIERS] = {NULL,}; -#endif + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(route_info, AUDIO_ERR_PARAMETER); if (ah->modem.is_connected) { - AUDIO_LOG_INFO("modem is connected, skip verb[%s]", verb); + AUDIO_LOG_WARN("modem is connected, skip verb[%s]", verb); return audio_ret; } if (ah->device.mode != VERB_NORMAL) { - if (ah->device.mode == VERB_VOICECALL) { - __reset_voice_devices_info(ah); - COND_SIGNAL(ah->device.device_cond, "device_cond"); + if (ah->device.mode == VERB_RADIO) { + if (ah->device.is_radio_on && !ah->modem.is_connected) { + /* Skip setting NORMAL VERB and keep going with RADIO VERB */ + AUDIO_LOG_WARN("radio is in progress, skip verb[%s]", verb); + verb = mode_to_verb_str[VERB_RADIO]; + } else if (!ah->device.is_radio_on) { + if ((audio_ret = _fmradio_pcm_close(ah))) + AUDIO_LOG_ERROR("failed to _fmradio_pcm_close(), ret(0x%x)", audio_ret); + } + } else { + if (ah->device.mode == VERB_VOICECALL) { + __reset_voice_devices_info(ah); + COND_SIGNAL(ah->device.device_cond, "device_cond"); + } + _reset_pcm_devices(ah); + ah->device.mode = VERB_NORMAL; } - _reset_pcm_devices(ah); - ah->device.mode = VERB_NORMAL; } - AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); - AUDIO_RETURN_VAL_IF_FAIL(route_info, AUDIO_ERR_PARAMETER); - devices = route_info->device_infos; AUDIO_LOG_INFO("update_route_ap_playback_capture++ "); @@ -198,28 +217,7 @@ static audio_return_t __update_route_ap_playback_capture(audio_hal_t *ah, audio_ AUDIO_LOG_ERROR("Failed to set devices: error = 0x%x", audio_ret); return audio_ret; } - ah->device.mode = VERB_NORMAL; -#if 0 /* Disable setting modifiers, because driver does not support it yet */ - /* Set modifiers */ - if (!strncmp("voice_recognition", route_info->role, MAX_NAME_LEN)) { - modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_VOICESEARCH; - } else if ((!strncmp("alarm", route_info->role, MAX_NAME_LEN))||(!strncmp("notifiication", route_info->role, MAX_NAME_LEN))) { - if (ah->device.active_out &= AUDIO_DEVICE_OUT_JACK) - modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_DUAL_MEDIA; - else - modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_MEDIA; - } else if (!strncmp("ringtone", route_info->role, MAX_NAME_LEN)) { - if (ah->device.active_out) - modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_RINGTONE; - } else { - if (ah->device.active_in) - modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_CAMCORDING; - else - modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_MEDIA; - } - audio_ret = _audio_ucm_set_modifiers (ah, verb, modifiers); -#endif return audio_ret; } @@ -273,6 +271,40 @@ static audio_return_t __update_route_voip(audio_hal_t *ah, device_info_t *device return audio_ret; } +static audio_return_t __update_route_fmradio(audio_hal_t *ah, device_info_t *devices, int32_t num_of_devices) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + const char *verb = mode_to_verb_str[VERB_RADIO]; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER); + + AUDIO_LOG_INFO("update_route_fmradio++"); + + if (!ah->device.fmradio_pcm_out) { + if ((audio_ret = _fmradio_pcm_open(ah))) { + AUDIO_LOG_ERROR("Failed to _fmradio_pcm_open(): error = 0x%x", audio_ret); + return audio_ret; + } + _audio_volume_set_level_radio(ah, 0); + } + + audio_ret = __set_devices(ah, verb, devices, num_of_devices); + if (audio_ret) { + AUDIO_LOG_ERROR("Failed to set devices: error = 0x%x", audio_ret); + return audio_ret; + } + /* FIXME. If necessary, set VERB_VOIP */ + ah->device.mode = VERB_RADIO; + + _audio_volume_set_level_radio(ah, ah->volume.volume_level[AUDIO_VOLUME_TYPE_MEDIA]); + if ((audio_ret = __connect_fm_radio(ah))) + AUDIO_LOG_ERROR("failed to __connect_fm_radio(), ret(0x%x)", audio_ret); + + /* TO DO: Set modifiers */ + return audio_ret; +} + static audio_return_t __update_route_reset(audio_hal_t *ah, uint32_t direction) { audio_return_t audio_ret = AUDIO_RET_OK; @@ -307,11 +339,16 @@ static audio_return_t __update_route_reset(audio_hal_t *ah, uint32_t direction) } } if (ah->device.mode == VERB_VOICECALL) { - _voice_pcm_close(ah, direction); + if ((audio_ret = _voice_pcm_close(ah, direction))) + AUDIO_LOG_ERROR("failed to _voice_pcm_close(), ret(0x%x)", audio_ret); if (!ah->device.active_in && !ah->device.active_out) ah->device.mode = VERB_NORMAL; __reset_voice_devices_info(ah); COND_SIGNAL(ah->device.device_cond, "device_cond"); + } else if (ah->device.mode == VERB_RADIO) { + if ((audio_ret = _fmradio_pcm_close(ah))) + AUDIO_LOG_ERROR("failed to _fmradio_pcm_close(), ret(0x%x)", audio_ret); + ah->device.mode = VERB_NORMAL; } if (active_devices[0] == NULL) { @@ -339,6 +376,7 @@ audio_return_t _audio_routing_init(audio_hal_t *ah) ah->device.active_in = 0x0; ah->device.active_out = 0x0; ah->device.mode = VERB_NORMAL; + ah->device.is_radio_on = 0; if ((audio_ret = _ucm_init(ah))) AUDIO_LOG_ERROR("failed to _ucm_init(), ret(0x%x)", audio_ret); @@ -432,6 +470,10 @@ audio_return_t audio_update_route(void *audio_handle, audio_route_info_t *info) if ((audio_ret = __update_route_voip(ah, devices, info->num_of_devices))) AUDIO_LOG_WARN("update voip route return 0x%x", audio_ret); + } else if (!strncmp("radio", info->role, MAX_NAME_LEN)) { + if ((audio_ret = __update_route_fmradio(ah, devices, info->num_of_devices))) + AUDIO_LOG_WARN("update radio route return 0x%x", audio_ret); + } else if (!strncmp("reset", info->role, MAX_NAME_LEN)) { if ((audio_ret = __update_route_reset(ah, devices->direction))) AUDIO_LOG_WARN("update reset return 0x%x", audio_ret); diff --git a/tizen-audio-stream.c b/tizen-audio-stream.c index f89a0b6..582b1aa 100644 --- a/tizen-audio-stream.c +++ b/tizen-audio-stream.c @@ -27,6 +27,7 @@ #include <stdbool.h> #include "tizen-audio-internal.h" +#include "tizen-audio-impl.h" /* Audio latency */ static const char* AUDIO_LATENCY_LOW = "low"; @@ -108,6 +109,12 @@ audio_return_t audio_notify_stream_connection_changed(void *audio_handle, audio_ AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER); AUDIO_LOG_INFO("role:%s, direction:%u, idx:%u, is_connected:%d", info->role, info->direction, info->idx, is_connected); + if (streq(info->role, "radio")) { + if (is_connected) + ah->device.is_radio_on = 1; + else + ah->device.is_radio_on = 0; + } return audio_ret; } diff --git a/tizen-audio-volume.c b/tizen-audio-volume.c index 6d83d29..904e720 100644 --- a/tizen-audio-volume.c +++ b/tizen-audio-volume.c @@ -29,11 +29,17 @@ #include <iniparser.h> #include "tizen-audio-internal.h" +#include "tizen-audio-impl.h" #define VOLUME_INI_DEFAULT_PATH SYSCONFDIR"/multimedia/mmfw_audio_volume.ini" /* SYSCONFDIR is defined at .spec */ #define VOLUME_INI_TEMP_PATH "/opt/system/mmfw_audio_volume.ini" #define VOLUME_VALUE_MAX (1.0f) #define GAIN_VALUE_MAX (1.0f) +#define RADIO_TUNING_DEFUALT_FILE SYSCONFDIR"/multimedia/mmfw_fmradio.ini" +#define RADIO_TUNING_TEMP_FILE "/opt/system/.mmfw_fmradio.ini" +#define RADIO_TUNING_ENABLE "tuning:enable" +#define RADIO_TUNING_VOLUME_LEVELS "fmradio:volume_levels" +#define RADIO_TUNING_VOLUME_TABLE "fmradio:volume_table" static const char *g_volume_vconf[AUDIO_VOLUME_TYPE_MAX] = { "file/private/sound/volume/system", /* AUDIO_VOLUME_TYPE_SYSTEM */ @@ -252,12 +258,139 @@ static audio_return_t __load_volume_value_table_from_ini(audio_hal_t *ah) return AUDIO_RET_OK; } +static audio_return_t __load_radio_volume_table(int** volume_table, int *number_of_elements) +{ + dictionary * dict = NULL; + const char delimiter[] = ", "; + char* ptr = NULL; + char* token = NULL; + char* list_str = NULL; + int* temp_table = NULL; + int index = 0; + int ret = 0; + + bool tuning_enable = 0; + int not_found = -1; + int value = 0; + + dict = iniparser_load(RADIO_TUNING_DEFUALT_FILE); + if (dict == NULL) { + AUDIO_LOG_ERROR("%s load failed", RADIO_TUNING_DEFUALT_FILE); + return AUDIO_ERR_UNDEFINED; + } else { + /*tuning enable */ + value = iniparser_getboolean(dict, RADIO_TUNING_ENABLE, not_found); + if (value == not_found) { + AUDIO_LOG_ERROR("Can't get Tuning Enable value"); + } else { + tuning_enable = value; + AUDIO_LOG_INFO("Tuning enabled."); + } + iniparser_freedict(dict); /*Cleanup*/ + } + + if (tuning_enable) { + AUDIO_LOG_INFO("Tuning enabled. load temp tuning file."); + dict = iniparser_load(RADIO_TUNING_TEMP_FILE); + if (!dict) { + AUDIO_LOG_WARN("%s load failed. Tuning enabled but there is not tuning temp file. Use temporary file", RADIO_TUNING_TEMP_FILE); + dict = iniparser_load(RADIO_TUNING_DEFUALT_FILE); + if (!dict) { + AUDIO_LOG_ERROR("%s load failed", RADIO_TUNING_DEFUALT_FILE); + return AUDIO_ERR_UNDEFINED; + } + } + } else { + AUDIO_LOG_INFO("Tuning diabled. load default tuning file."); + dict = iniparser_load(RADIO_TUNING_DEFUALT_FILE); + if (!dict) { + AUDIO_LOG_ERROR("%s load failed", RADIO_TUNING_DEFUALT_FILE); + return AUDIO_ERR_UNDEFINED; + } + } + + *number_of_elements = iniparser_getint(dict, RADIO_TUNING_VOLUME_LEVELS, -1); + if (*number_of_elements == -1) { + ret = AUDIO_ERR_INTERNAL; + goto error; + } + temp_table = (int *)malloc ((*number_of_elements) * sizeof(int)); + if (!temp_table) { + goto error; + } + *volume_table = temp_table; + + list_str = iniparser_getstring(dict, RADIO_TUNING_VOLUME_TABLE, NULL); + if (list_str) { + token = strtok_r(list_str, delimiter, &ptr); + while (token) { + temp_table[index] = atoi(token); + AUDIO_LOG_INFO("fm volume index %d is %d", index, temp_table[index]); + index++; + token = strtok_r(NULL, delimiter, &ptr); + } + } +error: + iniparser_freedict(dict); + return ret; +} + +audio_return_t _audio_volume_set_level_radio(audio_hal_t *ah, uint32_t level) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + + int volume = 0; + int mute = -1; + + /* Applying mute at volume zero */ + if (level == 0) { + if ((audio_ret = _mixer_control_set_value(ah, MIXER_FMRADIO_MUTE, 0))) + AUDIO_LOG_ERROR("set mixer(%s) failed", MIXER_FMRADIO_MUTE); + + } else { + if ((audio_ret = _mixer_control_get_value(ah, MIXER_FMRADIO_MUTE, &mute))) { + AUDIO_LOG_ERROR("get mixer(%s) failed", MIXER_FMRADIO_MUTE); + return audio_ret; + } + if (mute == 0) { + if ((audio_ret = _mixer_control_set_value(ah, MIXER_FMRADIO_MUTE, 1))) { + AUDIO_LOG_ERROR("set mixer(%s) failed", MIXER_FMRADIO_MUTE); + return audio_ret; + } + } + } + + if ((_mixer_control_get_value(ah, MIXER_FMRADIO_L_VOLUME, &volume))) + AUDIO_LOG_ERROR("get mixer(%s) failed", MIXER_FMRADIO_L_VOLUME); + else { + if (volume != ah->volume.radio_volume_value_table[level]) { + if ((audio_ret = _mixer_control_set_value(ah, MIXER_FMRADIO_L_VOLUME, ah->volume.radio_volume_value_table[level]))) { + AUDIO_LOG_ERROR("set mixer(%s) failed", MIXER_FMRADIO_L_VOLUME); + return audio_ret; + } + } + } + + if ((_mixer_control_get_value(ah, MIXER_FMRADIO_R_VOLUME, &volume))) + AUDIO_LOG_ERROR("get mixer(%s) failed", MIXER_FMRADIO_R_VOLUME); + else { + if (volume != ah->volume.radio_volume_value_table[level]) { + if ((audio_ret = _mixer_control_set_value(ah, MIXER_FMRADIO_R_VOLUME, ah->volume.radio_volume_value_table[level]))) + AUDIO_LOG_ERROR("set mixer(%s) failed", MIXER_FMRADIO_R_VOLUME); + } + } + + return audio_ret; +} + audio_return_t _audio_volume_init(audio_hal_t *ah) { int i; int val = 0; audio_return_t audio_ret = AUDIO_RET_OK; int init_value[AUDIO_VOLUME_TYPE_MAX] = { 9, 11, 7, 11, 7, 4, 4, 7 }; + int* fm_table = NULL; + int number_of_steps = 0; AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); @@ -287,6 +420,18 @@ audio_return_t _audio_volume_init(audio_hal_t *ah) return AUDIO_ERR_UNDEFINED; } + /* radio volume table */ + __load_radio_volume_table(&fm_table, &number_of_steps); + if (fm_table) { + AUDIO_LOG_DEBUG("number of steps -> %d", number_of_steps); + /*copy from temp structure to main strcture*/ + for (i = 0; i < number_of_steps; i++) { + ah->volume.radio_volume_value_table[i] = fm_table[i]; + } + free(fm_table); + fm_table = NULL; + } + return audio_ret; } @@ -366,6 +511,8 @@ audio_return_t audio_set_volume_level(void *audio_handle, audio_volume_info_t *i AUDIO_LOG_INFO("set [%s] volume_level: %d, direction(%d)", info->type, level, info->direction); /* set mixer related to H/W volume if needed */ + if ((__get_volume_idx_by_string_type(info->type) == AUDIO_VOLUME_TYPE_MEDIA) && ah->device.is_radio_on) + audio_ret = _audio_volume_set_level_radio(ah, level); return audio_ret; } |