summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packaging/audio-hal-sc7727.spec2
-rw-r--r--tizen-audio-impl-pcm.c128
-rw-r--r--tizen-audio-impl-ucm.c18
-rw-r--r--tizen-audio-impl.h26
-rw-r--r--tizen-audio-internal.h10
-rw-r--r--tizen-audio-modem.c45
-rw-r--r--tizen-audio-pcm.c1
-rw-r--r--tizen-audio-routing.c112
-rw-r--r--tizen-audio-stream.c7
-rw-r--r--tizen-audio-volume.c147
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;
}