Initial bring-up of voice routing 76/134076/7 accepted/tizen/4.0/unified/20170816.012336 accepted/tizen/unified/20170703.064201 submit/tizen/20170629.105304 submit/tizen_4.0/20170811.094300
authorSeungbae Shin <seungbae.shin@samsung.com>
Wed, 14 Jun 2017 11:17:23 +0000 (20:17 +0900)
committerSeungbae Shin <seungbae.shin@samsung.com>
Wed, 28 Jun 2017 08:12:15 +0000 (17:12 +0900)
open voice DAI with samplerate(48k)/channels(2)
adjust capture/playback DAI open/close sequence
open capture/playback DAI together before ucm set

[Version] 0.1.2
[Profile] Wearable
[Issue Type] Bring-up

Change-Id: Ic32abecdf6088f67660403a9dfa84138ff90f975

Makefile.am
packaging/audio-hal-wm1831-tw2.spec
tizen-audio-impl-pcm.c
tizen-audio-impl-ucm.c
tizen-audio-impl.h
tizen-audio-internal.h
tizen-audio-routing.c

index 2543080..a7c112d 100644 (file)
@@ -10,12 +10,10 @@ libtizen_audio_la_SOURCES = tizen-audio.c \
                tizen-audio-impl-ucm.c \
                tizen-audio-impl-ctrl.c
 libtizen_audio_la_LDFLAGS = $(AM_LDFLAGS) -disable-static -avoid-version
+libtizen_audio_la_LIBADD = $(AM_LDADD) $(ASOUNDLIB_LIBS) $(VCONF_LIBS) $(DLOG_LIBS) $(INIPARSER_LIBS) $(EXPAT_LIBS)
+libtizen_audio_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) $(VCONF_CFLAGS) $(DLOG_CFLAGS) $(INIPARSER_CFLAGS) $(EXPAT_CFLAGS) -DUSE_DLOG
+
 if USE_TINYALSA
-libtizen_audio_la_LIBADD = $(AM_LDADD) $(ASOUNDLIB_LIBS) $(TINYALSA_LIBS) $(VCONF_LIBS) $(DLOG_LIBS) $(INIPARSER_LIBS)
-libtizen_audio_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) $(TINYALSA_CFLAGS) $(VCONF_CFLAGS) $(DLOG_CFLAGS) $(INIPARSER_CFLAGS) -D__USE_TINYALSA__
-else
-libtizen_audio_la_LIBADD = $(AM_LDADD) $(ASOUNDLIB_LIBS) $(VCONF_LIBS) $(DLOG_LIBS) $(INIPARSER_LIBS)
-libtizen_audio_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) $(VCONF_CFLAGS) $(DLOG_CFLAGS) $(INIPARSER_CFLAGS)
+libtizen_audio_la_LIBADD += $(TINYALSA_LIBS)
+libtizen_audio_la_CFLAGS += $(TINYALSA_CFLAGS) -D__USE_TINYALSA__
 endif
-libtizen_audio_la_CFLAGS += -DUSE_DLOG
-
index 80802f9..2fd151c 100644 (file)
@@ -1,6 +1,6 @@
 Name:       audio-hal-wm1831-tw2
 Summary:    TIZEN Audio HAL for WM1831(TW2)
-Version:    0.1.0
+Version:    0.1.2
 Release:    0
 Group:      System/Libraries
 License:    Apache-2.0
index 926de2c..908576e 100644 (file)
@@ -58,11 +58,84 @@ static const uint32_t g_format_convert_table[] = {
 };
 #endif
 
+#define VOICE_PCM_SAMPLERATE 48000
+#define VOICE_PCM_CHANNELS 2
+
 static uint32_t __convert_format(audio_sample_format_t format)
 {
     return g_format_convert_table[format];
 }
 
+/* #define DEBUG_TIMING */
+
+static int __voice_pcm_set_params(audio_hal_t *ah, snd_pcm_t *pcm)
+{
+    snd_pcm_hw_params_t *params = NULL;
+    int err = 0;
+    unsigned int val = 0;
+
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(pcm, AUDIO_ERR_PARAMETER);
+
+    /* Skip parameter setting to null device. */
+    if (snd_pcm_type(pcm) == SND_PCM_TYPE_NULL)
+        return AUDIO_ERR_IOCTL;
+
+    /* Allocate a hardware parameters object. */
+    snd_pcm_hw_params_alloca(&params);
+
+    /* Fill it in with default values. */
+    if (snd_pcm_hw_params_any(pcm, params) < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params_any() : failed! - %s\n", snd_strerror(err));
+        goto error;
+    }
+
+    /* Set the desired hardware parameters. */
+    /* Interleaved mode */
+    err = snd_pcm_hw_params_set_access(pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED);
+    if (err < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params_set_access() : failed! - %s\n", snd_strerror(err));
+        goto error;
+    }
+    err = snd_pcm_hw_params_set_rate(pcm, params, VOICE_PCM_SAMPLERATE, 0);
+    if (err < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params_set_rate() : failed! - %s\n", snd_strerror(err));
+        goto error;
+    }
+    err = snd_pcm_hw_params_set_channels(pcm, params, VOICE_PCM_CHANNELS);
+    if (err < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params_set_channels() : failed! - %s\n", snd_strerror(err));
+        goto error;
+    }
+    err = snd_pcm_hw_params(pcm, params);
+    if (err < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params() : failed! - %s\n", snd_strerror(err));
+        goto error;
+    }
+
+    /* Dump current param */
+    snd_pcm_hw_params_get_access(params, (snd_pcm_access_t *) &val);
+    AUDIO_LOG_DEBUG("access type = %s\n", snd_pcm_access_name((snd_pcm_access_t)val));
+
+    snd_pcm_hw_params_get_format(params, (snd_pcm_format_t*)&val);
+    AUDIO_LOG_DEBUG("format = '%s' (%s)\n",
+                    snd_pcm_format_name((snd_pcm_format_t)val),
+                    snd_pcm_format_description((snd_pcm_format_t)val));
+
+    snd_pcm_hw_params_get_subformat(params, (snd_pcm_subformat_t *)&val);
+    AUDIO_LOG_DEBUG("subformat = '%s' (%s)\n",
+                    snd_pcm_subformat_name((snd_pcm_subformat_t)val),
+                    snd_pcm_subformat_description((snd_pcm_subformat_t)val));
+
+    snd_pcm_hw_params_get_channels(params, &val);
+    AUDIO_LOG_DEBUG("channels = %d\n", val);
+
+    return 0;
+
+error:
+    return -1;
+}
+
 #ifdef __USE_TINYALSA__
 static struct pcm *__tinyalsa_open_device(audio_pcm_sample_spec_t *ss, size_t period_size, size_t period_count, uint32_t direction)
 {
@@ -119,6 +192,120 @@ static int __tinyalsa_pcm_recover(struct pcm *pcm, int err)
 }
 #endif
 
+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("Setup Voice DAIs");
+
+    /* Voice Capture DAI */
+    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));
+        ret = AUDIO_ERR_IOCTL;
+        goto error;
+    }
+    ret = __voice_pcm_set_params(ah, ah->device.pcm_in);
+    if (ret != 0) {
+        AUDIO_LOG_ERROR("voice capture DAI(%s, %p) setparam failure", VOICE_PCM_DEVICE, ah->device.pcm_in);
+        ret = AUDIO_ERR_INTERNAL;
+        goto error;
+    }
+    AUDIO_LOG_INFO("voice capture DAI(%s, %p) open/setparam success", VOICE_PCM_DEVICE, ah->device.pcm_in);
+
+    /* Voice Playback DAI */
+    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));
+        ret = AUDIO_ERR_IOCTL;
+        goto error;
+    }
+    ret = __voice_pcm_set_params(ah, ah->device.pcm_out);
+    if (ret != 0) {
+        AUDIO_LOG_ERROR("voice playback DAI(%s, %p) setparam failure", VOICE_PCM_DEVICE, ah->device.pcm_out);
+        ret = AUDIO_ERR_INTERNAL;
+        goto error;
+    }
+    AUDIO_LOG_INFO("voice playback DAI(%s, %p) open/setparam success", VOICE_PCM_DEVICE, ah->device.pcm_out);
+#endif
+
+    return AUDIO_RET_OK;
+
+error:
+    if (ah->device.pcm_out) {
+        snd_pcm_close(ah->device.pcm_out);
+        ah->device.pcm_out = NULL;
+    }
+    if (ah->device.pcm_in) {
+        snd_pcm_close(ah->device.pcm_in);
+        ah->device.pcm_in = NULL;
+    }
+    return ret;
+}
+
+bool _is_voice_pcm_opened(audio_hal_t *ah)
+{
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+
+    if (ah->device.pcm_in && ah->device.pcm_out)
+        return true;
+    else
+        return false;
+}
+
+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)) {
+        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)) {
+        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;
+}
+
+audio_return_t _reset_pcm_devices(audio_hal_t *ah)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+
+    if (ah->device.pcm_out) {
+        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) {
+        if (!(audio_ret = _pcm_close(ah->device.pcm_in))) {
+            ah->device.pcm_in = NULL;
+            AUDIO_LOG_INFO("pcm_in handle close success");
+        }
+    }
+
+    return audio_ret;
+}
+
 audio_return_t _pcm_open(void **pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods)
 {
 #ifdef __USE_TINYALSA__
@@ -213,7 +400,7 @@ audio_return_t _pcm_close(void *pcm_handle)
 {
     int err;
 
-    AUDIO_LOG_INFO("Try to close PCM handle 0x%x", pcm_handle);
+    AUDIO_LOG_INFO("Try to close PCM handle %p", pcm_handle);
 
 #ifdef __USE_TINYALSA__
     if ((err = pcm_close(pcm_handle)) < 0) {
@@ -613,3 +800,157 @@ audio_return_t _pcm_set_params(void *pcm_handle, uint32_t direction, void *sampl
 
     return AUDIO_RET_OK;
 }
+
+/* Generic snd pcm interface APIs */
+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)
+{
+    audio_return_t ret = AUDIO_RET_OK;
+    snd_pcm_hw_params_t *hwparams;
+    int err = 0;
+    int dir;
+    unsigned int val = 0;
+    snd_pcm_uframes_t _period_size = period_size ? *period_size : 0;
+    snd_pcm_uframes_t _buffer_size = buffer_size ? *buffer_size : 0;
+    uint8_t _use_mmap = use_mmap && *use_mmap;
+    uint32_t channels = 0;
+
+    AUDIO_RETURN_VAL_IF_FAIL(pcm, AUDIO_ERR_PARAMETER);
+
+    snd_pcm_hw_params_alloca(&hwparams);
+
+    /* Skip parameter setting to null device. */
+    if (snd_pcm_type(pcm) == SND_PCM_TYPE_NULL)
+        return AUDIO_ERR_IOCTL;
+
+    /* Allocate a hardware parameters object. */
+    snd_pcm_hw_params_alloca(&hwparams);
+
+    /* Fill it in with default values. */
+    if (snd_pcm_hw_params_any(pcm, hwparams) < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params_any() : failed! - %s\n", snd_strerror(err));
+        goto error;
+    }
+
+    /* Set the desired hardware parameters. */
+
+    if (_use_mmap) {
+
+        if (snd_pcm_hw_params_set_access(pcm, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) {
+
+            /* mmap() didn't work, fall back to interleaved */
+
+            if ((ret = snd_pcm_hw_params_set_access(pcm, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
+                AUDIO_LOG_DEBUG("snd_pcm_hw_params_set_access() failed: %s", snd_strerror(ret));
+                goto error;
+            }
+
+            _use_mmap = 0;
+        }
+
+    } else if ((ret = snd_pcm_hw_params_set_access(pcm, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
+        AUDIO_LOG_DEBUG("snd_pcm_hw_params_set_access() failed: %s", snd_strerror(ret));
+        goto error;
+    }
+    AUDIO_LOG_DEBUG("setting rate - %d", sample_spec->rate);
+    err = snd_pcm_hw_params_set_rate(pcm, hwparams, sample_spec->rate, 0);
+    if (err < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params_set_rate() : failed! - %s\n", snd_strerror(err));
+    }
+
+    err = snd_pcm_hw_params(pcm, hwparams);
+    if (err < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params() : failed! - %s\n", snd_strerror(err));
+        goto error;
+    }
+
+    /* Dump current param */
+
+    if ((ret = snd_pcm_hw_params_current(pcm, hwparams)) < 0) {
+        AUDIO_LOG_INFO("snd_pcm_hw_params_current() failed: %s", snd_strerror(ret));
+        goto error;
+    }
+
+    if ((ret = snd_pcm_hw_params_get_period_size(hwparams, &_period_size, &dir)) < 0 ||
+        (ret = snd_pcm_hw_params_get_buffer_size(hwparams, &_buffer_size)) < 0) {
+        AUDIO_LOG_INFO("snd_pcm_hw_params_get_{period|buffer}_size() failed: %s", snd_strerror(ret));
+        goto error;
+    }
+
+    snd_pcm_hw_params_get_access(hwparams, (snd_pcm_access_t *) &val);
+    AUDIO_LOG_DEBUG("access type = %s\n", snd_pcm_access_name((snd_pcm_access_t)val));
+
+    snd_pcm_hw_params_get_format(hwparams, &sample_spec->format);
+    AUDIO_LOG_DEBUG("format = '%s' (%s)\n",
+                    snd_pcm_format_name((snd_pcm_format_t)sample_spec->format),
+                    snd_pcm_format_description((snd_pcm_format_t)sample_spec->format));
+
+    snd_pcm_hw_params_get_subformat(hwparams, (snd_pcm_subformat_t *)&val);
+    AUDIO_LOG_DEBUG("subformat = '%s' (%s)\n",
+                    snd_pcm_subformat_name((snd_pcm_subformat_t)val),
+                    snd_pcm_subformat_description((snd_pcm_subformat_t)val));
+
+    snd_pcm_hw_params_get_channels(hwparams, &channels);
+    sample_spec->channels = (uint8_t)channels;
+    AUDIO_LOG_DEBUG("channels = %d\n", sample_spec->channels);
+
+    if (buffer_size)
+        *buffer_size = _buffer_size;
+
+    if (period_size)
+        *period_size = _period_size;
+
+    if (use_mmap)
+        *use_mmap = _use_mmap;
+
+    return AUDIO_RET_OK;
+
+error:
+    return AUDIO_ERR_RESOURCE;
+}
+
+audio_return_t _pcm_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, uint8_t period_event)
+{
+    snd_pcm_sw_params_t *swparams;
+    snd_pcm_uframes_t boundary;
+    int err;
+
+    AUDIO_RETURN_VAL_IF_FAIL(pcm, AUDIO_ERR_PARAMETER);
+
+    snd_pcm_sw_params_alloca(&swparams);
+
+    if ((err = snd_pcm_sw_params_current(pcm, swparams)) < 0) {
+        AUDIO_LOG_WARN("Unable to determine current swparams: %s\n", snd_strerror(err));
+        goto error;
+    }
+    if ((err = snd_pcm_sw_params_set_period_event(pcm, swparams, period_event)) < 0) {
+        AUDIO_LOG_WARN("Unable to disable period event: %s\n", snd_strerror(err));
+        goto error;
+    }
+    if ((err = snd_pcm_sw_params_set_tstamp_mode(pcm, swparams, SND_PCM_TSTAMP_ENABLE)) < 0) {
+        AUDIO_LOG_WARN("Unable to enable time stamping: %s\n", snd_strerror(err));
+        goto error;
+    }
+    if ((err = snd_pcm_sw_params_get_boundary(swparams, &boundary)) < 0) {
+        AUDIO_LOG_WARN("Unable to get boundary: %s\n", snd_strerror(err));
+        goto error;
+    }
+    if ((err = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, boundary)) < 0) {
+        AUDIO_LOG_WARN("Unable to set stop threshold: %s\n", snd_strerror(err));
+        goto error;
+    }
+    if ((err = snd_pcm_sw_params_set_start_threshold(pcm, swparams, (snd_pcm_uframes_t) avail_min)) < 0) {
+        AUDIO_LOG_WARN("Unable to set start threshold: %s\n", snd_strerror(err));
+        goto error;
+    }
+    if ((err = snd_pcm_sw_params_set_avail_min(pcm, swparams, avail_min)) < 0) {
+        AUDIO_LOG_WARN("snd_pcm_sw_params_set_avail_min() failed: %s", snd_strerror(err));
+        goto error;
+    }
+    if ((err = snd_pcm_sw_params(pcm, swparams)) < 0) {
+        AUDIO_LOG_WARN("Unable to set sw params: %s\n", snd_strerror(err));
+        goto error;
+    }
+    return AUDIO_RET_OK;
+error:
+    return err;
+}
index 2c42613..7ff7cbc 100644 (file)
@@ -369,7 +369,19 @@ audio_return_t _ucm_set_devices(audio_hal_t *ah, const char *verb, const char *d
     __dump_use_case(UCM_PREFIX_CURRENT, old_verb, old_dev_list, old_dev_count, NULL, 0);
 
     if (devices) {
-        for (dev_count = 0; devices[dev_count]; dev_count++);
+        if (streq(verb, "Voice")) {
+            /* In case of Voice verb with Bluetooth device, make this device alone */
+            for (dev_count = 0; devices[dev_count]; dev_count++) {
+                if (streq(devices[dev_count], "Bluetooth")) {
+                    devices = &devices[dev_count];
+                    dev_count = 1;
+                    AUDIO_LOG_DEBUG("Voice verb with Bluetooth device only");
+                    break;
+                }
+            }
+        } else {
+            for (dev_count = 0; devices[dev_count]; dev_count++);
+        }
     }
 
     __dump_use_case(UCM_PREFIX_REQUESTED, verb, devices, dev_count, NULL, 0);
@@ -648,4 +660,4 @@ audio_return_t _ucm_reset_use_case(audio_hal_t *ah)
     }
 
     return ret;
-}
\ No newline at end of file
+}
index 4287ac8..64daeaf 100644 (file)
@@ -21,6 +21,9 @@
  */
 
 /* PCM */
+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);
index 0236e8a..b2ab3b7 100644 (file)
@@ -86,14 +86,10 @@ enum audio_device_type {
     AUDIO_DEVICE_OUT_RECEIVER         = AUDIO_DEVICE_OUT | 0x00000002,
     AUDIO_DEVICE_OUT_JACK             = AUDIO_DEVICE_OUT | 0x00000004,
     AUDIO_DEVICE_OUT_BT_SCO           = AUDIO_DEVICE_OUT | 0x00000008,
-    AUDIO_DEVICE_OUT_AUX              = AUDIO_DEVICE_OUT | 0x00000010,
-    AUDIO_DEVICE_OUT_HDMI             = AUDIO_DEVICE_OUT | 0x00000020,
     AUDIO_DEVICE_OUT_ALL              = (AUDIO_DEVICE_OUT_SPEAKER |
                                          AUDIO_DEVICE_OUT_RECEIVER |
                                          AUDIO_DEVICE_OUT_JACK |
-                                         AUDIO_DEVICE_OUT_BT_SCO |
-                                         AUDIO_DEVICE_OUT_AUX |
-                                         AUDIO_DEVICE_OUT_HDMI),
+                                         AUDIO_DEVICE_OUT_BT_SCO),
     /* input devices */
     AUDIO_DEVICE_IN_MAIN_MIC          = AUDIO_DEVICE_IN | 0x00000001,
     AUDIO_DEVICE_IN_SUB_MIC           = AUDIO_DEVICE_IN | 0x00000002,
@@ -113,12 +109,8 @@ typedef struct device_type {
 /* Verbs */
 #define AUDIO_USE_CASE_VERB_INACTIVE                "Inactive"
 #define AUDIO_USE_CASE_VERB_HIFI                    "HiFi"
-
-/* Modifiers */
-#define AUDIO_USE_CASE_MODIFIER_VOICESEARCH              "VoiceSearch"
-#define AUDIO_USE_CASE_MODIFIER_CAMCORDING               "Camcording"
-#define AUDIO_USE_CASE_MODIFIER_MEDIA                    "Media"
-#define AUDIO_USE_CASE_MODIFIER_DUAL_MEDIA               "DualMedia"
+#define AUDIO_USE_CASE_VERB_VOICECALL               "Voice"
+#define AUDIO_USE_CASE_VERB_VOIP                    "VoIP"
 
 #define streq !strcmp
 #define strneq strcmp
@@ -126,6 +118,7 @@ typedef struct device_type {
 #define ALSA_DEFAULT_CARD       "universal7270la"
 #define PLAYBACK_PCM_DEVICE     "hw:0,0"
 #define CAPTURE_PCM_DEVICE      "hw:0,0"
+#define VOICE_PCM_DEVICE        "hw:0,1"
 
 /* hw:0,0 */
 #define PLAYBACK_CARD_ID        0
@@ -136,7 +129,6 @@ typedef struct device_type {
 #define CAPTURE_PCM_DEVICE_ID   0
 
 #define MAX_DEVICES             5
-#define MAX_MODIFIERS           5
 #define MAX_NAME_LEN           32
 
 /* type definitions */
@@ -152,6 +144,8 @@ typedef struct {
 /* Routing */
 typedef enum audio_route_mode {
     VERB_NORMAL,
+    VERB_VOICECALL,
+    VERB_VOIP,
 } audio_route_mode_t;
 
 typedef struct audio_hal_device {
@@ -262,6 +256,8 @@ audio_return_t _audio_stream_deinit(audio_hal_t *ah);
 audio_return_t _audio_pcm_init(audio_hal_t *ah);
 audio_return_t _audio_pcm_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);
+
 typedef struct _dump_data {
     char *strbuf;
     int left;
index 99bf6ca..ffa629d 100644 (file)
 
 static device_type_t outDeviceTypes[] = {
     { AUDIO_DEVICE_OUT_SPEAKER, "speaker" },
-    { AUDIO_DEVICE_OUT_JACK, "Headphones" },
     { AUDIO_DEVICE_OUT_BT_SCO, "bt-sco-headset" },
-    { AUDIO_DEVICE_OUT_AUX, "Line" },
-    { AUDIO_DEVICE_OUT_HDMI, "HDMI" },
     { 0, 0 },
 };
 
 static device_type_t inDeviceTypes[] = {
     { AUDIO_DEVICE_IN_MAIN_MIC, "main-mic" },
-    { AUDIO_DEVICE_IN_JACK, "HeadsetMic" },
     { AUDIO_DEVICE_IN_BT_SCO, "bt-sco-mic" },
     { 0, 0 },
 };
 
 static const char* mode_to_verb_str[] = {
     AUDIO_USE_CASE_VERB_HIFI,
+    AUDIO_USE_CASE_VERB_VOICECALL,
+    AUDIO_USE_CASE_VERB_VOIP,
 };
 
 static uint32_t __convert_device_string_to_enum(const char* device_str, uint32_t direction)
@@ -57,20 +55,10 @@ static uint32_t __convert_device_string_to_enum(const char* device_str, uint32_t
 
     if (!strncmp(device_str, "builtin-speaker", MAX_NAME_LEN)) {
         device = AUDIO_DEVICE_OUT_SPEAKER;
-    } else if (!strncmp(device_str, "builtin-receiver", MAX_NAME_LEN)) {
-        device = AUDIO_DEVICE_OUT_RECEIVER;
-    } else if ((!strncmp(device_str, "audio-jack", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_OUT)) {
-        device = AUDIO_DEVICE_OUT_JACK;
     } else if ((!strncmp(device_str, "bt-sco", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_OUT)) {
         device = AUDIO_DEVICE_OUT_BT_SCO;
-    } else if (!strncmp(device_str, "aux", MAX_NAME_LEN)) {
-        device = AUDIO_DEVICE_OUT_AUX;
-    } else if (!strncmp(device_str, "hdmi", MAX_NAME_LEN)) {
-        device = AUDIO_DEVICE_OUT_HDMI;
     } else if ((!strncmp(device_str, "builtin-mic", MAX_NAME_LEN))) {
         device = AUDIO_DEVICE_IN_MAIN_MIC;
-    } else if ((!strncmp(device_str, "audio-jack", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_IN)) {
-        device = AUDIO_DEVICE_IN_JACK;
     } else if ((!strncmp(device_str, "bt-sco", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_IN)) {
         device = AUDIO_DEVICE_IN_BT_SCO;
     } else {
@@ -80,6 +68,22 @@ static uint32_t __convert_device_string_to_enum(const char* device_str, uint32_t
     return device;
 }
 
+static void __reset_voice_devices_info(audio_hal_t *ah)
+{
+    AUDIO_RETURN_IF_FAIL(ah);
+
+    AUDIO_LOG_INFO("reset voice device info");
+#if 0
+    if (ah->device.init_call_devices) {
+        free(ah->device.init_call_devices);
+        ah->device.init_call_devices = NULL;
+        ah->device.num_of_call_devices = 0;
+    }
+#endif
+
+    return;
+}
+
 static audio_return_t __set_devices(audio_hal_t *ah, const char *verb, device_info_t *devices, uint32_t num_of_devices)
 {
     audio_return_t audio_ret = AUDIO_RET_OK;
@@ -157,11 +161,23 @@ static audio_return_t __update_route_ap_playback_capture(audio_hal_t *ah, audio_
     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
     AUDIO_RETURN_VAL_IF_FAIL(route_info, AUDIO_ERR_PARAMETER);
 
-    devices = route_info->device_infos;
+#if 0
+    if (ah->modem.is_connected) {
+        AUDIO_LOG_WARN("modem is connected, skip verb[%s]", verb);
+        return audio_ret;
+    }
+#endif
 
-    /* To Do: Set modifiers */
-    /* int mod_idx = 0; */
-    /* const char *modifiers[MAX_MODIFIERS] = {NULL,}; */
+    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");
+        }
+       _reset_pcm_devices(ah);
+       ah->device.mode = VERB_NORMAL;
+    }
+
+    devices = route_info->device_infos;
 
     AUDIO_LOG_INFO("update_route_ap_playback_capture++ ");
 
@@ -170,25 +186,36 @@ 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;
 
-    /* To Do: 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;
+    return audio_ret;
+}
+
+static audio_return_t __update_route_voicecall(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_VOICECALL];
+
+    AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+    /* if both params are 0, return error for invalid state,
+         * this error would be used to tizen-audio-modem.c */
+    AUDIO_RETURN_VAL_IF_FAIL((devices||num_of_devices), AUDIO_ERR_INVALID_STATE);
+    AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER);
+
+    AUDIO_LOG_INFO("update_route_voicecall++");
+
+    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;
+    }
+
+    if (ah->device.mode != VERB_VOICECALL) {
+        ah->device.mode = VERB_VOICECALL;
+        /* FIXME. Get network info and configure rate in pcm device */
     } else {
-        if (ah->device.active_in)
-            modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_CAMCORDING;
-        else
-            modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_MEDIA;
+        if (!_is_voice_pcm_opened(ah))
+            _voice_pcm_open(ah);
     }
-    audio_ret = _audio_ucm_set_modifiers (ah, verb, modifiers);
-    */
 
     return audio_ret;
 }
@@ -221,10 +248,6 @@ static audio_return_t __update_route_reset(audio_hal_t *ah, uint32_t direction)
     const char *active_devices[MAX_DEVICES] = {NULL,};
     int i = 0, dev_idx = 0;
 
-    /* FIXME: If you need to reset, set verb inactive */
-    /* const char *verb = NULL; */
-    /* verb = AUDIO_USE_CASE_VERB_INACTIVE; */
-
     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
 
     AUDIO_LOG_INFO("update_route_reset++, direction(0x%x)", direction);
@@ -252,6 +275,14 @@ static audio_return_t __update_route_reset(audio_hal_t *ah, uint32_t direction)
             }
         }
     }
+    if (ah->device.mode == VERB_VOICECALL) {
+        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");
+    }
 
     if (active_devices[0] == NULL) {
         AUDIO_LOG_DEBUG("active device is NULL, no need to update.");
@@ -264,6 +295,11 @@ static audio_return_t __update_route_reset(audio_hal_t *ah, uint32_t direction)
     return audio_ret;
 }
 
+audio_return_t _audio_update_route_voicecall(audio_hal_t *ah, device_info_t *devices, int32_t num_of_devices)
+{
+    return __update_route_voicecall(ah, devices, num_of_devices);
+}
+
 audio_return_t _audio_routing_init(audio_hal_t *ah)
 {
     audio_return_t audio_ret = AUDIO_RET_OK;
@@ -306,7 +342,12 @@ audio_return_t audio_update_route(void *audio_handle, audio_route_info_t *info)
 
     devices = info->device_infos;
 
-    if (!strncmp("voip", info->role, MAX_NAME_LEN)) {
+    if (!strncmp("call-voice", info->role, MAX_NAME_LEN)) {
+        if ((audio_ret = __update_route_voicecall(ah, devices, info->num_of_devices)))
+            AUDIO_LOG_WARN("update voicecall route return 0x%x", audio_ret);
+
+//        COND_SIGNAL(ah->device.device_cond, "device_cond");
+    } else if (!strncmp("voip", info->role, MAX_NAME_LEN)) {
         if ((audio_ret = __update_route_voip(ah, devices, info->num_of_devices)))
             AUDIO_LOG_WARN("update voip route return 0x%x", audio_ret);