diff options
Diffstat (limited to 'avsys-audio-path.c')
-rw-r--r-- | avsys-audio-path.c | 2318 |
1 files changed, 2318 insertions, 0 deletions
diff --git a/avsys-audio-path.c b/avsys-audio-path.c new file mode 100644 index 0000000..7967842 --- /dev/null +++ b/avsys-audio-path.c @@ -0,0 +1,2318 @@ +/* + * avsystem + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jonghyuk Choi <jhchoi.choi@samsung.com> + * + * 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. + * + */ + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <stdlib.h> + +#include "avsys-audio-shm.h" +#include "avsys-audio-sync.h" +#include "avsys-audio-path.h" +#include "avsys-audio-shm.h" +#include "avsys-debug.h" +#include "avsys-common.h" +#include "avsys-audio-handle.h" +#include "avsys-audio-logical-volume.h" +#include "avsys-audio-alsa.h" +#include "avsys-audio-ascenario.h" + +#define EXPORT_API __attribute__((__visibility__("default"))) + +#define RET_IO_CTL_ERR_IF_FAIL(SECTION) { if(AVSYS_FAIL(SECTION)) { \ + avsys_error_r(AVAUDIO,"%s %d\n",__func__,__LINE__); \ + return AVSYS_STATE_ERR_IO_CONTROL; \ + } } + +#define OPEN_AIF_BEFORE_SCENARIO_SET + +static int g_playback_path_select_data[AVSYS_AUDIO_PLAYBACK_GAIN_MAX][AVSYS_AUDIO_PATH_EX_OUTMAX] = { + { /* AVSYS_AUDIO_PLAYBACK_GAIN_AP */ + /* NONE SPK RECV HEADSET BTHEADSET A2DP HANDSFREE HDMI */ + 0, 1, 0, 1, 0, 0, 0, 0 + }, + { /* AVSYS_AUDIO_PLAYBACK_GAIN_FMRADIO */ + /* NONE SPK RECV HEADSET BTHEADSET A2DP HANDSFREE HDMI */ + 1, 1, 0, 1, 0, 0, 0, 0 + }, + { /* AVSYS_AUDIO_PLAYBACK_GAIN_VOICECALL */ + /* NONE SPK RECV HEADSET BTHEADSET A2DP HANDSFREE HDMI */ + 1, 1, 1, 1, 1, 0, 0, 0 + }, + { /* AVSYS_AUDIO_PLAYBACK_GAIN_VIDEOCALL */ + /* NONE SPK RECV HEADSET BTHEADSET A2DP HANDSFREE HDMI */ + 1, 1, 1, 1, 1, 0, 0, 0 + }, + { /* AVSYS_AUDIO_PLAYBACK_GAIN_CALLALERT */ + /* NONE SPK RECV HEADSET BTHEADSET A2DP HANDSFREE HDMI */ + 0, 1, 1, 1, 1, 0, 0, 0 + } +}; + +static int g_capture_path_select_data[AVSYS_AUDIO_CAPTURE_GAIN_MAX][AVSYS_AUDIO_PATH_EX_INMAX] = { + { /* AVSYS_AUDIO_CAPTURE_GAIN_AP */ + /* NONE MIC HMIC BMIC FMIN HFREE */ + 1, 1, 1, 1, 0, 0 + }, + { /* AVSYS_AUDIO_CAPTURE_GAIN_FMRADIO */ + /* NONE MIC HMIC BMIC FMIN HFREE */ + 1, 0, 0, 0, 1, 0 + }, + { /* AVSYS_AUDIO_CAPTURE_GAIN_VOICECALL */ + /* NONE MIC HMIC BMIC FMIN HFREE */ + 1, 1, 1, 1, 0, 0 + }, + { /* AVSYS_AUDIO_CAPTURE_GAIN_VIDEOCALL */ + /* NONE MIC HMIC BMIC FMIN HFREE */ + 1, 1, 1, 1, 0, 0 + }, +}; + +static int g_playback_gain_select_data[AVSYS_AUDIO_PLAYBACK_GAIN_MAX][AVSYS_AUDIO_PLAYBACK_GAIN_MAX] = { + { /* AVSYS_AUDIO_PLAYBACK_GAIN_AP */ + AVSYS_AUDIO_PLAYBACK_GAIN_AP, /* AVSYS_AUDIO_PLAYBACK_GAIN_AP */ + AVSYS_AUDIO_PLAYBACK_GAIN_FMRADIO, /* AVSYS_AUDIO_PLAYBACK_GAIN_FMRADIO */ + AVSYS_AUDIO_PLAYBACK_GAIN_VOICECALL, /* AVSYS_AUDIO_PLAYBACK_GAIN_VOICECALL */ + AVSYS_AUDIO_PLAYBACK_GAIN_VIDEOCALL, /* AVSYS_AUDIO_PLAYBACK_GAIN_VIDEOCALL */ + AVSYS_AUDIO_PLAYBACK_GAIN_CALLALERT, /* AVSYS_AUDIO_PLAYBACK_GAIN_CALLALERT */ + }, + { /* AVSYS_AUDIO_PLAYBACK_GAIN_FMRADIO */ + AVSYS_AUDIO_PLAYBACK_GAIN_FMRADIO, /* AVSYS_AUDIO_PLAYBACK_GAIN_AP */ + AVSYS_AUDIO_PLAYBACK_GAIN_FMRADIO, /* AVSYS_AUDIO_PLAYBACK_GAIN_FMRADIO */ + AVSYS_AUDIO_PLAYBACK_GAIN_VOICECALL, /* AVSYS_AUDIO_PLAYBACK_GAIN_VOICECALL */ + AVSYS_AUDIO_PLAYBACK_GAIN_VIDEOCALL, /* AVSYS_AUDIO_PLAYBACK_GAIN_VIDEOCALL */ + AVSYS_AUDIO_PLAYBACK_GAIN_FMRADIO, /* AVSYS_AUDIO_PLAYBACK_GAIN_CALLALERT */ + }, + { /* AVSYS_AUDIO_PLAYBACK_GAIN_VOICECALL */ + AVSYS_AUDIO_PLAYBACK_GAIN_VOICECALL, /* AVSYS_AUDIO_PLAYBACK_GAIN_AP */ + AVSYS_AUDIO_PLAYBACK_GAIN_VOICECALL, /* AVSYS_AUDIO_PLAYBACK_GAIN_FMRADIO */ + AVSYS_AUDIO_PLAYBACK_GAIN_VOICECALL, /* AVSYS_AUDIO_PLAYBACK_GAIN_VOICECALL */ + AVSYS_AUDIO_PLAYBACK_GAIN_VIDEOCALL, /* AVSYS_AUDIO_PLAYBACK_GAIN_VIDEOCALL */ + AVSYS_AUDIO_PLAYBACK_GAIN_CALLALERT, /* AVSYS_AUDIO_PLAYBACK_GAIN_CALLALERT */ + }, + { /* AVSYS_AUDIO_PLAYBACK_GAIN_VIDEOCALL */ + AVSYS_AUDIO_PLAYBACK_GAIN_VIDEOCALL, /* AVSYS_AUDIO_PLAYBACK_GAIN_AP */ + AVSYS_AUDIO_PLAYBACK_GAIN_VIDEOCALL, /* AVSYS_AUDIO_PLAYBACK_GAIN_FMRADIO */ + AVSYS_AUDIO_PLAYBACK_GAIN_VOICECALL, /* AVSYS_AUDIO_PLAYBACK_GAIN_VOICECALL */ + AVSYS_AUDIO_PLAYBACK_GAIN_VIDEOCALL, /* AVSYS_AUDIO_PLAYBACK_GAIN_VIDEOCALL */ + AVSYS_AUDIO_PLAYBACK_GAIN_CALLALERT, /* AVSYS_AUDIO_PLAYBACK_GAIN_CALLALERT */ + }, + { /* AVSYS_AUDIO_PLAYBACK_GAIN_CALLALERT */ + AVSYS_AUDIO_PLAYBACK_GAIN_AP, /* AVSYS_AUDIO_PLAYBACK_GAIN_AP */ + AVSYS_AUDIO_PLAYBACK_GAIN_FMRADIO, /* AVSYS_AUDIO_PLAYBACK_GAIN_FMRADIO */ + AVSYS_AUDIO_PLAYBACK_GAIN_VOICECALL, /* AVSYS_AUDIO_PLAYBACK_GAIN_VOICECALL */ + AVSYS_AUDIO_PLAYBACK_GAIN_VIDEOCALL, /* AVSYS_AUDIO_PLAYBACK_GAIN_VIDEOCALL */ + AVSYS_AUDIO_PLAYBACK_GAIN_CALLALERT, /* AVSYS_AUDIO_PLAYBACK_GAIN_CALLALERT */ + }, +}; + +static int g_capture_gain_select_data[AVSYS_AUDIO_CAPTURE_GAIN_MAX][AVSYS_AUDIO_CAPTURE_GAIN_MAX] = { + { /* AVSYS_AUDIO_CAPTURE_GAIN_AP */ + AVSYS_AUDIO_CAPTURE_GAIN_AP, /* AVSYS_AUDIO_CAPTURE_GAIN_AP */ + AVSYS_AUDIO_CAPTURE_GAIN_FMRADIO, /* AVSYS_AUDIO_CAPTURE_GAIN_FMRADIO */ + AVSYS_AUDIO_CAPTURE_GAIN_VOICECALL, /* AVSYS_AUDIO_CAPTURE_GAIN_VOICECALL */ + AVSYS_AUDIO_CAPTURE_GAIN_VIDEOCALL, /* AVSYS_AUDIO_CAPTURE_GAIN_VIDEOCALL */ + }, + { /* AVSYS_AUDIO_CAPTURE_GAIN_FMRADIO */ + AVSYS_AUDIO_CAPTURE_GAIN_FMRADIO, /* AVSYS_AUDIO_CAPTURE_GAIN_AP */ + AVSYS_AUDIO_CAPTURE_GAIN_FMRADIO, /* AVSYS_AUDIO_CAPTURE_GAIN_FMRADIO */ + AVSYS_AUDIO_CAPTURE_GAIN_VOICECALL, /* AVSYS_AUDIO_CAPTURE_GAIN_VOICECALL */ + AVSYS_AUDIO_CAPTURE_GAIN_VIDEOCALL, /* AVSYS_AUDIO_CAPTURE_GAIN_VIDEOCALL */ + }, + { /* AVSYS_AUDIO_CAPTURE_GAIN_VOICECALL */ + AVSYS_AUDIO_CAPTURE_GAIN_VOICECALL, /* AVSYS_AUDIO_CAPTURE_GAIN_AP */ + AVSYS_AUDIO_CAPTURE_GAIN_VOICECALL, /* AVSYS_AUDIO_CAPTURE_GAIN_FMRADIO */ + AVSYS_AUDIO_CAPTURE_GAIN_VOICECALL, /* AVSYS_AUDIO_CAPTURE_GAIN_VOICECALL */ + AVSYS_AUDIO_CAPTURE_GAIN_VIDEOCALL, /* AVSYS_AUDIO_CAPTURE_GAIN_VIDEOCALL */ + }, + { /* AVSYS_AUDIO_CAPTURE_GAIN_VIDEOCALL */ + AVSYS_AUDIO_CAPTURE_GAIN_VIDEOCALL, /* AVSYS_AUDIO_CAPTURE_GAIN_AP */ + AVSYS_AUDIO_CAPTURE_GAIN_VIDEOCALL, /* AVSYS_AUDIO_CAPTURE_GAIN_FMRADIO */ + AVSYS_AUDIO_CAPTURE_GAIN_VOICECALL, /* AVSYS_AUDIO_CAPTURE_GAIN_VOICECALL */ + AVSYS_AUDIO_CAPTURE_GAIN_VIDEOCALL, /* AVSYS_AUDIO_CAPTURE_GAIN_VIDEOCALL */ + }, +}; + + +static int __avsys_audio_path_set_ascn_ap_playback(avsys_audio_path_ex_info_t *control); +static int __avsys_audio_path_set_ascn_voicecall(avsys_audio_path_ex_info_t *control); +static int __avsys_audio_path_set_ascn_videocall(avsys_audio_path_ex_info_t *control); +static int __avsys_audio_path_set_ascn_fmradio(avsys_audio_path_ex_info_t *control); +static int __avsys_audio_path_set_ascn_ap_capture(avsys_audio_path_ex_info_t *control); + + +typedef int (*_internal_gain_func)(avsys_audio_path_ex_info_t *control); +static _internal_gain_func playback_gain_func_table[AVSYS_AUDIO_PLAYBACK_GAIN_MAX] = +{ + __avsys_audio_path_set_ascn_ap_playback, + __avsys_audio_path_set_ascn_fmradio, + __avsys_audio_path_set_ascn_voicecall, + __avsys_audio_path_set_ascn_videocall, + __avsys_audio_path_set_ascn_ap_playback, +}; + +static _internal_gain_func capture_gain_func_table[AVSYS_AUDIO_CAPTURE_GAIN_MAX] = +{ + __avsys_audio_path_set_ascn_ap_capture, + __avsys_audio_path_set_ascn_fmradio, + __avsys_audio_path_set_ascn_voicecall, + __avsys_audio_path_set_ascn_videocall, +}; + +static int __avsys_audio_path_set_hw_controls(avsys_audio_path_ex_info_t *control); +static int __avsys_audio_path_get_earjack_type(void); + +#define AUDIOSYSTEM_CONF "/opt/etc/audio_system.conf" +#define CONF_ITEM_COUNT 2 +#define INPUT_DEV_MAX 20 +static char *conf_string[] = { + "headset_detection", + "headset_node", +}; + +typedef struct { + char headset_detection; + char headset_node_number; +} AudioSystemConf; + +static int __load_conf(AudioSystemConf *data) +{ +#if defined(_MMFW_I386_ALL_SIMULATOR) + if (data == NULL) + return AVSYS_STATE_ERR_NULL_POINTER; + + data->headset_detection = 1; + data->headset_node_number = 4; +#else + FILE *fp = NULL; + int i = 0; + char buffer[64] = { 0, }; + char conf_data[CONF_ITEM_COUNT] = { 1, 0 }; + + if (data == NULL) + return AVSYS_STATE_ERR_NULL_POINTER; + + fp = fopen(AUDIOSYSTEM_CONF, "r"); + if (fp == NULL) { + char filename[128] = { 0, }; + char readBuffer[32] = { 0, }; + char headset_find = 0; + int num = 0, headset_num = -1; + + for (num = 0; num < INPUT_DEV_MAX; num++) { + FILE *sfp = NULL; + memset(filename, '\0', sizeof(filename)); + snprintf(filename, sizeof(filename), "/sys/class/input/input%01d/name", num); + if (NULL == (sfp = fopen(filename, "r"))) + continue; + memset(readBuffer, '\0', sizeof(readBuffer)); + if (NULL == fgets(readBuffer, sizeof(readBuffer) - 1, sfp)) { + fclose(sfp); + continue; + } + if (strstr(readBuffer, "Headset")) { + headset_find = 1; + headset_num = num; + } + + fclose(sfp); + if (headset_num != -1) { + break; + } + } + if (headset_num == -1) + return AVSYS_STATE_ERR_INTERNAL; + + if (NULL == (fp = fopen(AUDIOSYSTEM_CONF, "w"))) { + return AVSYS_STATE_ERR_INTERNAL; + } + + fprintf(fp, "%s:1\n", conf_string[0]); + fprintf(fp, "%s:%d\n", conf_string[1], headset_num); + fflush(fp); + fclose(fp); + fp = NULL; + sync(); + data->headset_detection = 1; + data->headset_node_number = headset_num; + return AVSYS_STATE_SUCCESS; + } + + while (fgets(buffer, sizeof(buffer) - 1, fp) != NULL) { + if ((strlen(buffer) < 3) || (buffer[0] == '#') || (buffer[0] == '!')) + continue; + if (buffer[strlen(buffer) - 1] == '\n') + buffer[strlen(buffer) - 1] = '\0'; + for (i = 0; i < CONF_ITEM_COUNT; i++) { + if (0 == strncmp(buffer, conf_string[i], strlen(conf_string[i]))) { + char *ptr = NULL; + if (NULL == (ptr = strstr(buffer, ":"))) + break; + conf_data[i] = atoi(ptr + 1); + avsys_warning(AVAUDIO, "%s[%d]\n", buffer, conf_data[i]); + } + } + } + fclose(fp); + data->headset_detection = conf_data[0]; + data->headset_node_number = conf_data[1]; +#endif + return AVSYS_STATE_SUCCESS; +} + +EXPORT_API +int avsys_audio_path_ex_init(void) +{ + avsys_audio_path_ex_info_t *control = NULL; + avsys_audio_path_ex_info_t **temp = NULL; + gain_info_t default_gain = { AVSYS_AUDIO_PLAYBACK_GAIN_AP, AVSYS_AUDIO_CAPTURE_GAIN_AP }; + path_info_t default_path = { AVSYS_AUDIO_PATH_EX_SPK, AVSYS_AUDIO_PATH_EX_MIC }; + gain_status_t clean_gain_status = { GS_GAIN_NONE, GS_GAIN_NONE }; + path_status_t clean_path_status = { PS_PATH_NONE, PS_PATH_NONE }; + option_info_t default_option = { AVSYS_AUDIO_PATH_OPTION_JACK_AUTO, AVSYS_AUDIO_PATH_OPTION_JACK_AUTO }; + int index = 0; + int err = AVSYS_STATE_SUCCESS; + AudioSystemConf conf = { 1, 4 }; + + /* Check root user */ + err = avsys_check_root_privilege(); + if (AVSYS_FAIL(err)) { + return err; + } + + temp = &control; + avsys_assert(AVSYS_SUCCESS(avsys_audio_create_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))); + avsys_assert(AVSYS_SUCCESS(avsys_audio_create_sync(AVSYS_AUDIO_SYNC_IDEN_SOUNDPATH))); /* for audio route policy */ + avsys_assert(AVSYS_SUCCESS(avsys_audio_create_shm(AVSYS_AUDIO_SHM_IDEN_PATH))); + + avsys_assert(AVSYS_SUCCESS(avsys_audio_get_shm(AVSYS_AUDIO_SHM_IDEN_PATH, (void **)temp))); + if (control == NULL) + return AVSYS_STATE_ERR_NULL_POINTER; + + /* init values */ + control->pregain = default_gain; + control->gain = default_gain; + control->reqgain = default_gain; + control->path = default_path; + control->backup_gain = default_gain; + control->backup_path = default_path; + control->option = default_option; + control->gain_status = clean_gain_status; + control->path_status = clean_path_status; + control->p_gain_status = clean_gain_status; + control->p_path_status = clean_path_status; + + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_SPK; + control->inserted = AVSYS_AUDIO_INSERTED_NONE; + control->route_policy = AVSYS_AUDIO_ROUTE_POLICY_DEFAULT; + if (AVSYS_FAIL(__load_conf(&conf))) + avsys_error_r(AVAUDIO, "Can not load audio system configuration file\n"); + + if (conf.headset_detection) { + control->inserted = __avsys_audio_path_get_earjack_type(); + if (control->inserted == AVSYS_AUDIO_INSERTED_NONE) + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_SPK; + else + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_HEADSET; + } else { + avsys_warning(AVAUDIO, "Ignore headset detection. Use speaker device\n"); + control->inserted = AVSYS_AUDIO_INSERTED_NONE; + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_SPK; + } + + avsys_error_r(AVAUDIO, "Earjack init value is %d\n", control->inserted); + + { + /* Gain tunning Debug mode */ + FILE *gainTunningFp = NULL; + if (NULL != (gainTunningFp = fopen("/opt/etc/gain_tuner.ini", "r"))) { + char buffer[32] = ""; + avsys_warning(AVAUDIO, "GAIN TUNNING DEBUG MODE...This degrade sound path performance\n"); + memset(buffer, '\0', sizeof(buffer)); + if (NULL == fgets(buffer, sizeof(buffer) - 1, gainTunningFp)) { + fclose(gainTunningFp); + control->gain_debug_mode = 0; + } else { + fclose(gainTunningFp); + if (0 == strncmp("debug=1", buffer, 7)) { + control->gain_debug_mode = 1; + } else { + control->gain_debug_mode = 0; + } + } + } else { + control->gain_debug_mode = 0; + } + } + control->ear_auto = AVSYS_AUDIO_EAR_SWITCH_MANUAL; + control->mute = AVSYS_AUDIO_UNMUTE; + control->path_fixed = PATH_FIXED_NONE; + + index = 0; + do { + control->pathlock_pid[index] = -1; + index++; + } while (index < AVSYS_AUDIO_LOCK_SLOT_MAX); + + index = 0; + do { + control->path_fixed_pid[index] = -1; + index++; + } while (index < PATH_FIXED_TYPE_MAX); + + /* call path control */ + err = __avsys_audio_path_set_ascn_ap_playback(control); + if (AVSYS_SUCCESS(err)) + err = __avsys_audio_path_set_hw_controls(control); + + if (AVSYS_SUCCESS(err)) + err = __avsys_audio_path_set_ascn_ap_capture(control); + + return err; +} + +EXPORT_API +int avsys_audio_path_ex_fini(void) +{ + if (AVSYS_FAIL(avsys_audio_remove_shm(AVSYS_AUDIO_SHM_IDEN_PATH))) { + avsys_error_r(AVAUDIO, "avsys_audio_remove_shm() failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } + if (AVSYS_FAIL(avsys_audio_remove_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))) { + avsys_error_r(AVAUDIO, "avsys_audio_remove_sync() failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } + return AVSYS_STATE_SUCCESS; +} + +EXPORT_API +int avsys_audio_path_ex_reset(int forced) +{ + avsys_audio_path_ex_info_t *control = NULL; + avsys_audio_path_ex_info_t **temp = NULL; + gain_info_t default_gain = { AVSYS_AUDIO_PLAYBACK_GAIN_AP, AVSYS_AUDIO_CAPTURE_GAIN_AP }; + path_info_t default_path = { AVSYS_AUDIO_PATH_EX_SPK, AVSYS_AUDIO_PATH_EX_MIC }; + gain_status_t clean_gain_status = { GS_GAIN_NONE, GS_GAIN_NONE }; + path_status_t clean_path_status = { PS_PATH_NONE, PS_PATH_NONE }; + option_info_t default_option = { AVSYS_AUDIO_PATH_OPTION_JACK_AUTO, AVSYS_AUDIO_PATH_OPTION_JACK_AUTO }; + int index = 0; + int err = AVSYS_STATE_SUCCESS; + int backup_debug = 0; + AudioSystemConf conf = { 1, 4 }; + + /* Check root user */ + err = avsys_check_root_privilege(); + if (AVSYS_FAIL(err)) { + return err; + } + + temp = &control; + if (AVSYS_FAIL(avsys_audio_get_shm(AVSYS_AUDIO_SHM_IDEN_PATH, (void **)temp))) { + avsys_error_r(AVAUDIO, "avsys_audio_get_shm() failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } + if (control == NULL) + return AVSYS_STATE_ERR_NULL_POINTER; + + if (AVSYS_FAIL(avsys_audio_lock_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))) { + avsys_error_r(AVAUDIO, "avsys_audio_lock_sync() failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } + + /* init values */ + control->pregain = default_gain; + control->gain = default_gain; + control->reqgain = default_gain; + control->path = default_path; + control->backup_gain = default_gain; + control->backup_path = default_path; + control->option = default_option; + control->gain_status = clean_gain_status; + control->path_status = clean_path_status; + control->p_gain_status = clean_gain_status; + control->p_path_status = clean_path_status; + + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_SPK; + control->inserted = AVSYS_AUDIO_INSERTED_NONE; + control->route_policy = AVSYS_AUDIO_ROUTE_POLICY_DEFAULT; + if (AVSYS_FAIL(__load_conf(&conf))) + avsys_error_r(AVAUDIO, "Can not load audio system configuration file\n"); + + if (conf.headset_detection) { + control->inserted = __avsys_audio_path_get_earjack_type(); + if (control->inserted == AVSYS_AUDIO_INSERTED_NONE) + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_SPK; + else + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_HEADSET; + } else { + avsys_warning(AVAUDIO, "Ignore headset detection. Use speaker device\n"); + control->inserted = AVSYS_AUDIO_INSERTED_NONE; + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_SPK; + } + + avsys_error_r(AVAUDIO, "Earjack init value is %d\n", control->inserted); + + { + /* Gain tunning Debug mode */ + FILE *gainTunningFp = NULL; + if (NULL != (gainTunningFp = fopen("/opt/etc/gain_tuner.ini", "r"))) { + char buffer[32] = ""; + avsys_warning(AVAUDIO, "GAIN TUNNING DEBUG MODE...This degrade sound path performance\n"); + memset(buffer, '\0', sizeof(buffer)); + if (NULL == fgets(buffer, sizeof(buffer) - 1, gainTunningFp)) { + fclose(gainTunningFp); + control->gain_debug_mode = 0; + } else { + fclose(gainTunningFp); + if (0 == strncmp("debug=1", buffer, 7)) { + control->gain_debug_mode = 1; + } else { + control->gain_debug_mode = 0; + } + } + } else { + control->gain_debug_mode = 0; + } + } + control->ear_auto = AVSYS_AUDIO_EAR_SWITCH_MANUAL; + control->mute = AVSYS_AUDIO_UNMUTE; + control->path_fixed = PATH_FIXED_NONE; + + index = 0; + do { + control->pathlock_pid[index] = -1; + index++; + } while (index < AVSYS_AUDIO_LOCK_SLOT_MAX); + + index = 0; + do { + control->path_fixed_pid[index] = -1; + index++; + } while (index < PATH_FIXED_TYPE_MAX); + + if (forced) { + backup_debug = control->gain_debug_mode; + control->gain_debug_mode = 1; + } + /* call path control */ + err = __avsys_audio_path_set_ascn_ap_playback(control); + if (AVSYS_SUCCESS(err)) + err = __avsys_audio_path_set_hw_controls(control); + + if (AVSYS_SUCCESS(err)) + err = __avsys_audio_path_set_ascn_ap_capture(control); + + if (forced) { + control->gain_debug_mode = backup_debug; + } + + if (AVSYS_FAIL(avsys_audio_unlock_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))) { + avsys_error_r(AVAUDIO, "avsys_audio_unlock_sync() failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } + + return err; +} + +EXPORT_API +int avsys_audio_path_ex_dump(void) +{ + avsys_audio_path_ex_info_t *control = NULL; + avsys_audio_path_ex_info_t **temp = NULL; + const static char *str_earType[] = { "None", "EarOnly", "EarMic", "TVout" }; + const static char *str_yn[] = { "NO", "YES" }; + const static char *str_ear[] = { "MANUAL", "AUTO_MUTE", "AUTO_NOMUTE" }; + const static char *str_out[AVSYS_AUDIO_PATH_EX_OUTMAX] = { + "NONE", "SPK", "RECV", "HEADSET", "BTHEADSET", "A2DP", "HANSFREE" + }; + const static char *str_in[AVSYS_AUDIO_PATH_EX_INMAX] = { + "NONE", "MIC", "HEADMIC", "BTMIC", "FMINPUT", "HANSFREEMIC" + }; + const static char *str_route[AVSYS_AUDIO_ROUTE_POLICY_MAX] = { + "DEFAULT", "IGN_A2DP", "HANDSET" + }; + /* + const static char *str_gain[AVSYS_AUDIO_GAIN_EX_MAX] = { + "KEYTONE", "RINGTONE", "ALARMTONE", "CALLTONE", "AUDIOPLAYER", "VIDEOPLAYER", + "VOICECALL", "VIDEOCALL", "FMRADIO", "VOICEREC", "CAMCORDER", "CAMERA", "GAME"}; + */ + const static char *str_playback_gain[AVSYS_AUDIO_PLAYBACK_GAIN_MAX] = { + "AP", "FMRADIO", "VOICECALL", "VIDEOCALL", "CALLALERT", + }; + const static char *str_capture_gain[AVSYS_AUDIO_CAPTURE_GAIN_MAX] = { + "AP", "FMRADIO", "VOICECALL", "VIDEOCALL", + }; + + int index = 0; + + temp = &control; + + if (AVSYS_FAIL(avsys_audio_get_shm(AVSYS_AUDIO_SHM_IDEN_PATH, (void **)temp))) { + avsys_error_r(AVAUDIO, "avsys_audio_get_shm() failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } + if (control == NULL) + return AVSYS_STATE_ERR_NULL_POINTER; + + fprintf(stdout, "======================================================================\n"); + fprintf(stdout, " Avsystem Audio Path Control Information \n"); + fprintf(stdout, "======================================================================\n"); +#if defined(_MMFW_I386_ALL_SIMULATOR) + fprintf(stdout, " In simulator, follow informations don`t have means.\n"); +#endif + + fprintf(stdout, " GAIN : P (%-s / %-s) - R (%-s / %-s) - C (%-s / %-s)\n", + str_playback_gain[control->pregain.playback], str_capture_gain[control->pregain.capture], + str_playback_gain[control->reqgain.playback], str_capture_gain[control->reqgain.capture], + str_playback_gain[control->gain.playback], str_capture_gain[control->gain.capture]); + fprintf(stdout, " Current Out / In : %-s / %-s\n", str_out[control->path.playback], str_in[control->path.capture] ); + fprintf(stdout, " Gain debug mode : 0x%-x\n", control->gain_debug_mode); + fprintf(stdout, " Gain status : 0x%x 0x%x\n", control->gain_status.playback, control->gain_status.capture); + fprintf(stdout, " Path status : 0x%x 0x%x\n", control->path_status.playback, control->path_status.capture); + fprintf(stdout, " Auto EarJack Control : %-s\n", str_ear[control->ear_auto]); + fprintf(stdout, " Audio Route Policy : %-s\n", str_route[control->route_policy]); + fprintf(stdout, " Physical Earjack? [type] : %-s [%-s]\n", str_yn[control->inserted != AVSYS_AUDIO_INSERTED_NONE], str_earType[control->inserted]); + fprintf(stdout, " Path Fixed State : 0x%-x\n", control->path_fixed); + fprintf(stdout, " Mute status : %d\n", control->mute); + if (control->path_fixed_pid[PATH_FIXED_TYPE_FMRADIO] != -1) + fprintf(stdout, " FM Radio path pid : %d\n", control->path_fixed_pid[PATH_FIXED_TYPE_FMRADIO]); + if (control->path_fixed_pid[PATH_FIXED_TYPE_CALL] != -1) + fprintf(stdout, " Call path pid : %d\n", control->path_fixed_pid[PATH_FIXED_TYPE_CALL]); + + index = 0; + do { + if (control->pathlock_pid[index] != -1) + fprintf(stdout, " Path sync lock required PIDs : %d\n", control->pathlock_pid[index]); + index++; + } while (index < AVSYS_AUDIO_LOCK_SLOT_MAX); + fprintf(stdout, " Option Lagacy : %-s\n", str_yn[(control->option.playback & AVSYS_AUDIO_PATH_OPTION_LEGACY_MODE) ? 1 : 0]); + fprintf(stdout, " Option Jack Playback : %-s\n", str_yn[(control->option.playback & AVSYS_AUDIO_PATH_OPTION_JACK_AUTO) ? 1 : 0]); + fprintf(stdout, " Option Jack Capture : %-s\n", str_yn[(control->option.capture & AVSYS_AUDIO_PATH_OPTION_JACK_AUTO) ? 1 : 0]); + fprintf(stdout, " Option Dual out : %-s\n", str_yn[(control->option.playback & AVSYS_AUDIO_PATH_OPTION_DUAL_OUT) ? 1 : 0]); + fprintf(stdout, " Option Forced : %-s\n", str_yn[(control->option.playback & AVSYS_AUDIO_PATH_OPTION_FORCED) ? 1 : 0]); + + return AVSYS_STATE_SUCCESS; +} + +static int __avsys_audio_path_get_earjack_type (void) +{ + int fd = 0; + char readval = AVSYS_AUDIO_INSERTED_NONE; + fd = open("/sys/devices/platform/jack/earjack_online", O_RDONLY); + + if (fd == -1) { + avsys_error_r(AVAUDIO, "Can not get initial jack type\n"); + return AVSYS_AUDIO_INSERTED_NONE; + } + read(fd, &readval, sizeof(readval)); + switch (readval) { + case '0': + readval = AVSYS_AUDIO_INSERTED_NONE; + break; + case '1': + readval = AVSYS_AUDIO_INSERTED_3; + break; + case '3': + readval = AVSYS_AUDIO_INSERTED_4; + break; + case '8': + readval = AVSYS_AUDIO_INSERTED_AV; + break; + case '2': + if (1 == read(fd, &readval, sizeof(readval))) { + if (readval == '0') { + readval = AVSYS_AUDIO_INSERTED_AV; + } else { + avsys_error(AVAUDIO, "Unknown jack type value...2%d\n", readval); + readval = AVSYS_AUDIO_INSERTED_NONE; + } + } else { + avsys_error(AVAUDIO, "jack type read error...\n"); + readval = AVSYS_AUDIO_INSERTED_NONE; + } + break; + default: + avsys_error(AVAUDIO, "jack type unknown value...%c\n", readval); + readval = AVSYS_AUDIO_INSERTED_NONE; + break; + } + + close(fd); + return readval; +} + +int avsys_audio_path_earjack_init(int *init_type, int *outfd) +{ +#if !defined(_MMFW_I386_ALL_SIMULATOR) + char eventnode_filename[32] = { 0, }; + int fd = 0; + AudioSystemConf conf = { 1, 4 }; + + if (outfd == NULL || init_type == NULL) { + avsys_error(AVAUDIO, "input parameter is null\n"); + return AVSYS_STATE_ERR_NULL_POINTER; + } + + if (AVSYS_FAIL(__load_conf(&conf))) { + avsys_error_r(AVAUDIO, "Can not load audio system configuration file\n"); + } + + if (!conf.headset_detection) { + avsys_error(AVAUDIO, "Earjack control daemon will be closed by user option...\n"); + return AVSYS_STATE_SUCCESS; + } + + snprintf(eventnode_filename, sizeof(eventnode_filename), "/dev/event%01d", conf.headset_node_number); + + fd = open(eventnode_filename, O_RDONLY); + if (fd == -1) { + avsys_error_r(AVAUDIO, "Device file open error\n"); + return AVSYS_STATE_ERR_INTERNAL; + } else { + avsys_audio_path_ex_info_t *control = NULL; + avsys_audio_path_ex_info_t **temp = NULL; + void *vol_data = NULL; + void *handle_data = NULL; + temp = &control; + + if(AVSYS_FAIL(avsys_audio_get_shm(AVSYS_AUDIO_SHM_IDEN_LVOLUME, &vol_data))) { + avsys_error(AVAUDIO,"attach logical volume shared memory failed\n"); + return AVSYS_STATE_ERR_ALLOCATION; + } + if(AVSYS_FAIL(avsys_audio_get_shm(AVSYS_AUDIO_SHM_IDEN_HANDLE, &handle_data))) { + avsys_error(AVAUDIO,"attach handle shared memory failed\n"); + return AVSYS_STATE_ERR_ALLOCATION; + } + if(AVSYS_FAIL(avsys_audio_get_shm(AVSYS_AUDIO_SHM_IDEN_PATH, (void**)temp))) { + avsys_error_r(AVAUDIO,"avsys_audio_get_shm() failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } + + *init_type = control->inserted; + *outfd = fd; + return AVSYS_STATE_SUCCESS; + } +#else + return AVSYS_STATE_ERR_DEVICE_NOT_SUPPORT; +#endif +} + +int avsys_audio_path_earjack_wait(int fd, int *current_type, int *new_type, int *is_auto_mute) +{ +#if !defined(_MMFW_I386_ALL_SIMULATOR) + fd_set set; + int readtemp; + int select_ret = 0; + struct avsys_audio_jack_event jevent; + int res = AVSYS_STATE_SUCCESS; + int set_flag = 0; + int cur_type = -1; + + if (new_type == NULL || is_auto_mute == NULL) + return AVSYS_STATE_ERR_NULL_POINTER; + + FD_ZERO(&set); + FD_SET(fd, &set); + + cur_type = *current_type; + + select_ret = select(fd + 1, &set, NULL, NULL, NULL); + avsys_info(AVAUDIO, "SELECT returns......\n"); + + if (select_ret != 1) { + if (select_ret == 0) { + avsys_error_r(AVAUDIO, "Earjack timeout in autocontrol\n"); + } else if (select_ret == -1) { + avsys_error_r(AVAUDIO, "Earjack detect unknown error: %d\n", errno); + } + return AVSYS_STATE_WAR_INVALID_VALUE; + } +#ifdef EARJACK_LOCK /* currently this is disabled to avoid semapore value increase */ + if (AVSYS_FAIL(avsys_audio_lock_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))) { + avsys_error_r(AVAUDIO, "avsys_audio_lock_sync() failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } +#endif + if (read(fd, &jevent, sizeof(jevent)) < 0) { + avsys_error(AVAUDIO, "read fd failed with 0x%x\n", errno); + return AVSYS_STATE_WAR_INVALID_MODE; + } + avsys_info(AVAUDIO, "*** JEVENT : code=%d, value=%d\n", jevent.code, jevent.value); + if (jevent.type != TYPE_EVENT_SWITCH) { + avsys_info(AVAUDIO, "Not a switch event\n"); + return AVSYS_STATE_WAR_INVALID_MODE; + } + + switch (jevent.code) { + case CODE_HEADPHONE_INSERT: + case CODE_LINEOUT_INSERT: + case CODE_JACK_PHYSICAL_INSERT: + if (jevent.value == 1) { + readtemp = __avsys_audio_path_get_earjack_type(); + } else { + readtemp = 0; + } + + set_flag = 1; /* need change earphone status */ + break; + default: + readtemp = cur_type; /* same value */ + break; + } + + *new_type = readtemp; + + avsys_audio_path_ex_info_t *control = NULL; + avsys_audio_path_ex_info_t **temp = NULL; + temp = &control; + + if (AVSYS_FAIL(avsys_audio_get_shm(AVSYS_AUDIO_SHM_IDEN_PATH, (void **)temp))) { + avsys_error_r(AVAUDIO, "avsys_audio_get_shm() failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } + + avsys_info(AVAUDIO, "control->ear_auto = %d\n", control->ear_auto); + if (control->ear_auto == AVSYS_AUDIO_EAR_SWITCH_AUTO_WITH_MUTE) { + *current_type = control->inserted; + *is_auto_mute = 1; + res = AVSYS_STATE_SUCCESS; + } else if (control->ear_auto == AVSYS_AUDIO_EAR_SWITCH_AUTO_WITHOUT_MUTE) { + *current_type = control->inserted; + *is_auto_mute = 0; + res = AVSYS_STATE_SUCCESS; + } else if (control->ear_auto == AVSYS_AUDIO_EAR_SWITCH_MANUAL) { + *is_auto_mute = 0; + /* return warning */ + if (set_flag) { + control->inserted = *new_type; + set_flag = 0; + } + res = AVSYS_STATE_WAR_INTERNAL; + } + + return res; +#else + return AVSYS_STATE_ERR_DEVICE_NOT_SUPPORT; +#endif +} + +int avsys_audio_path_earjack_process(int new_type) +{ +#if !defined(_MMFW_I386_ALL_SIMULATOR) + avsys_audio_path_ex_info_t *control = NULL; + avsys_audio_path_ex_info_t **temp = NULL; + int err = AVSYS_STATE_SUCCESS; + temp = &control; + + avsys_info(AVAUDIO, "new_type = %d\n", new_type); + if (AVSYS_FAIL(avsys_audio_get_shm(AVSYS_AUDIO_SHM_IDEN_PATH, (void **)temp))) { + avsys_error_r(AVAUDIO, "avsys_audio_get_shm() failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } + + control->inserted = new_type; + + if (control->ear_auto == AVSYS_AUDIO_EAR_SWITCH_MANUAL) { + return AVSYS_STATE_SUCCESS; + } + + /* Capture/Playback Gain Control */ + avsys_warning(AVAUDIO, "Gain C(%d), P(%d)\n", control->gain.capture, control->gain.playback); + err = capture_gain_func_table[control->gain.capture] (control); + if (AVSYS_FAIL(err)) { + avsys_error_r(AVAUDIO, "earjack change failed for %d gain : error 0x%x\n", control->gain.capture, err); + } + + err = playback_gain_func_table[control->gain.playback] (control); + if (AVSYS_SUCCESS(err)) { + /* H/W Control */ + err = __avsys_audio_path_set_hw_controls(control); + if (AVSYS_FAIL(err)) { + avsys_error_r(AVAUDIO, "__avsys_audio_path_set_hw_controls() failed in %s\n", __func__); + } + } else + avsys_error_r(AVAUDIO, "earjack change failed for %d gain : error 0x%x\n", control->gain.playback, err); + + return err; +#else + return AVSYS_STATE_ERR_DEVICE_NOT_SUPPORT; +#endif +} + +int avsys_audio_path_earjack_deinit(int fd) +{ +#if !defined(_MMFW_I386_ALL_SIMULATOR) + close(fd); + return AVSYS_STATE_SUCCESS; +#else + return AVSYS_STATE_ERR_DEVICE_NOT_SUPPORT; +#endif +} + +int avsys_audio_path_earjack_unlock() +{ +#ifdef EARJACK_LOCK /* currently this is disabled to avoid semapore value increase */ + if (AVSYS_FAIL(avsys_audio_unlock_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))) { + avsys_error_r(AVAUDIO, "avsys_audio_unlock_sync() failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } +#endif + return AVSYS_STATE_SUCCESS; +}; + +#define DO_IF_VALID(c, p) { if(c > -1) p; } +#define DO_IF_INVALID(c, p) { if(c == -1) p; } +#define CHECK_VALID(c) (c>-1 ? 1 : 0) + +enum { + CMD_DEVICE_NONE = 0, + CMD_DEVICE_OPEN, + CMD_DEVICE_CLOSE, + CMD_DEVICE_MAX +}; + +avsys_audio_alsa_aif_handle_t *g_hAIF[AIF_DEVICE_MAX] = { NULL, NULL, NULL, NULL }; +char *strAIF[AIF_DEVICE_MAX] = { "AIF2 Capture", "AIF2 Playback", "AIF3 Capture", "AIF3 Playback" }; + +#define SET_AIF(index) \ +do { \ + if(g_hAIF[index]) { \ + avsys_warning(AVAUDIO,#index" device already opened\n"); \ + AIF_control[index] = CMD_DEVICE_NONE; \ + } else { \ + AIF_control[index] = CMD_DEVICE_OPEN; \ + } \ +} while (0) + +static int __avsys_open_aif(char AIF_control[]) +{ + int iAIF = 0; + int err = AVSYS_STATE_SUCCESS; + + for (iAIF = 0; iAIF < AIF_DEVICE_MAX; iAIF++) { + /* check command */ + if (AIF_control[iAIF] != CMD_DEVICE_OPEN) + continue; + + /* check handle allocation */ + if (g_hAIF[iAIF]) { + avsys_warning(AVAUDIO, "Oops! Free %s device handle first", strAIF[iAIF]); + free(g_hAIF[iAIF]); + g_hAIF[iAIF] = NULL; + } + /* memory allocation for handle */ + avsys_warning(AVAUDIO, "%s handle alloc", strAIF[iAIF]); + g_hAIF[iAIF] = calloc(sizeof(avsys_audio_handle_t), 1); + if (!g_hAIF[iAIF]) { + avsys_error_r(AVAUDIO, "Can not alloc memory for %s device handle", strAIF[iAIF]); + err = AVSYS_STATE_ERR_ALLOCATION; + continue; + } + + if (AVSYS_FAIL(avsys_audio_alsa_open_AIF_device(iAIF, g_hAIF[iAIF]))) { + avsys_error_r(AVAUDIO, "open %s device failed\n", strAIF[iAIF]); + err = AVSYS_STATE_ERR_INVALID_HANDLE; + } else { + avsys_warning(AVAUDIO, "open %s device success\n", strAIF[iAIF]); + if (AVSYS_FAIL(avsys_audio_alsa_set_AIF_params(g_hAIF[iAIF]))) { + avsys_error_r(AVAUDIO, "%s device set parameter failed\n", strAIF[iAIF]); + err = AVSYS_STATE_ERR_INVALID_PARAMETER; + } else { + avsys_warning(AVAUDIO, "%s device set parameter success\n", strAIF[iAIF]); + } + } + } + return err; +} + +static void __avsys_close_aif () +{ + int iAIF = 0; + + for (iAIF = 0; iAIF < AIF_DEVICE_MAX; iAIF++) { + if (g_hAIF[iAIF]) { + avsys_info(AVAUDIO, "close device :: %s\n", strAIF[iAIF]); + if (AVSYS_FAIL(avsys_audio_alsa_close_AIF_device(g_hAIF[iAIF]))) { + avsys_error_r(AVAUDIO, "close %s device failed\n", strAIF[iAIF]); + } + free(g_hAIF[iAIF]); + g_hAIF[iAIF] = NULL; + avsys_warning(AVAUDIO, "%s device handle free\n", strAIF[iAIF]); + } else { + avsys_info(AVAUDIO, "skip closing device :: %s\n", strAIF[iAIF]); + } + } +} + +static int __avsys_audio_release_path (gain_info_t local_gain, avsys_audio_path_ex_info_t *control) +{ + int err = AVSYS_STATE_SUCCESS; + int iAIF = 0; + + avsys_warning(AVAUDIO, "Release path for %d %d\n", local_gain.playback, local_gain.capture); + + switch (local_gain.playback) { + case AVSYS_AUDIO_PLAYBACK_GAIN_VOICECALL: + case AVSYS_AUDIO_PLAYBACK_GAIN_VIDEOCALL: + if (getpid() == control->path_fixed_pid[PATH_FIXED_TYPE_CALL]) { +#ifndef OPEN_AIF_BEFORE_SCENARIO_SET /* FIXME : disable here, close after scenario set */ + __avsys_close_aif(); +#endif + + if (AVSYS_FAIL(avsys_audio_ascn_single_set(ASCN_CODEC_DISABLE_ON_SUSPEND))) { + avsys_error_r(AVAUDIO, "[%s] failed to set codec_disable_on_suspend\n", __func__); + } + control->p_path_status.playback |= PS_CODEC_DISABLE_ON_SUSPEND; + } else { + if (control->path_fixed_pid[PATH_FIXED_TYPE_CALL] < 0) { + avsys_warning(AVAUDIO, "Sound path for call released already\n"); + } else { + avsys_warning(AVAUDIO, "Try to close call path from other process.. original pid[%d]\n", control->path_fixed_pid[PATH_FIXED_TYPE_CALL]); + avsys_warning(AVAUDIO, "Just mark handle as off\n"); + } + } + + if ((control->path_fixed & PATH_FIXED_WITH_CALL) == 0) { + avsys_error(AVAUDIO, "Call path release without call path request\n"); + } + control->path_fixed &= ~PATH_FIXED_WITH_CALL; + control->path_fixed_pid[PATH_FIXED_TYPE_CALL] = -1; + + break; + + case AVSYS_AUDIO_PLAYBACK_GAIN_FMRADIO: + /* TODO: Reset & Codec disable on suspend script */ + if (AVSYS_FAIL(avsys_audio_ascn_single_set(ASCN_CODEC_DISABLE_ON_SUSPEND))) { + avsys_error_r(AVAUDIO, "[%s] failed to set codec_disable_on_suspend\n", __func__); + } + control->p_path_status.playback |= PS_CODEC_DISABLE_ON_SUSPEND; + + if (AVSYS_FAIL(avsys_audio_ascn_single_set(ASCN_STR_RESET))) { + avsys_error_r(AVAUDIO, "[%s] failed to set reset\n", __func__); + } else { + control->p_path_status.playback = PS_PATH_NONE; + } + + /* TODO: Path fixed clear (path_fixed, path_fixed_pid) */ + if ((control->path_fixed & PATH_FIXED_WITH_FMRADIO) == 0) { + avsys_error(AVAUDIO, "FM-Radio path release without radio path request\n"); + } + control->path_fixed &= ~PATH_FIXED_WITH_FMRADIO; + control->path_fixed_pid[PATH_FIXED_TYPE_FMRADIO] = -1; + break; + + default: + avsys_warning(AVAUDIO, "unexpected path release\n"); + break; + } + + if (control->path_fixed != PATH_FIXED_NONE) { + avsys_error(AVAUDIO, "Still remain another path_fixed request : 0x%08X\n", control->path_fixed); + avsys_error(AVAUDIO, "This is not expected condition\n"); + } else { + avsys_warning(AVAUDIO, "Path Release to default condition....\n"); + control->gain.playback = AVSYS_AUDIO_PLAYBACK_GAIN_AP; + control->gain.capture = AVSYS_AUDIO_CAPTURE_GAIN_AP; + control->path.playback = AVSYS_AUDIO_PATH_EX_SPK; + control->path.capture = AVSYS_AUDIO_PATH_EX_MIC; + + switch(control->route_policy) + { + case AVSYS_AUDIO_ROUTE_POLICY_DEFAULT: + case AVSYS_AUDIO_ROUTE_POLICY_IGNORE_A2DP: + control->ear_auto = AVSYS_AUDIO_EAR_SWITCH_AUTO_WITH_MUTE; + control->option.playback = AVSYS_AUDIO_PATH_OPTION_JACK_AUTO; + control->option.capture = AVSYS_AUDIO_PATH_OPTION_JACK_AUTO; + break; + + case AVSYS_AUDIO_ROUTE_POLICY_HANDSET_ONLY: + control->ear_auto = AVSYS_AUDIO_EAR_SWITCH_AUTO_WITHOUT_MUTE; + control->option.playback = AVSYS_AUDIO_PATH_OPTION_NONE; + control->option.capture = AVSYS_AUDIO_PATH_OPTION_NONE; + break; + + default: + break; + } + + control->p_path_status.playback = PS_PATH_NONE; + control->p_path_status.capture = PS_PATH_NONE; + control->p_gain_status.playback = GS_GAIN_NONE; + control->p_gain_status.capture = GS_GAIN_NONE; + + /* Playback */ + err = __avsys_audio_path_set_ascn_ap_playback(control); + if (AVSYS_SUCCESS(err)) { + err = __avsys_audio_path_set_hw_controls(control); + if (AVSYS_FAIL(err)) { + avsys_error(AVAUDIO, "Update logical volume failure\n"); + } + } else { + avsys_error(AVAUDIO, "Set ap playback failure\n"); + } + + /* Capture */ + err = __avsys_audio_path_set_ascn_ap_capture(control); + if (AVSYS_FAIL(err)) { + avsys_error(AVAUDIO, "Set ap capture failure\n"); + } + } + + /* FIXME : Close AIF, this will be moved before scneario set */ +#ifdef OPEN_AIF_BEFORE_SCENARIO_SET + if ((local_gain.playback == AVSYS_AUDIO_PLAYBACK_GAIN_VOICECALL || local_gain.playback == AVSYS_AUDIO_PLAYBACK_GAIN_VIDEOCALL) && + getpid() == control->path_fixed_pid[PATH_FIXED_TYPE_CALL]) { + __avsys_close_aif(); + } +#endif + + return err; +} + +int avsys_audio_path_ex_set_path(int gain, int out, int in, int option) +{ + avsys_audio_path_ex_info_t *control = NULL; + avsys_audio_path_ex_info_t **temp = NULL; + gain_info_t local_gain = { -1, -1 }; + gain_info_t req_gain = { -1, -1 }; + pid_t current_pid; + int err = AVSYS_STATE_SUCCESS; + char req_release_path = 0; + char AIF_control[AIF_DEVICE_MAX] = { CMD_DEVICE_NONE, CMD_DEVICE_NONE, CMD_DEVICE_NONE, CMD_DEVICE_NONE }; + int iAIF = 0; + + avsys_warning(AVAUDIO, "=================== [Input Param] gain %d, out %d, in %d, opt 0x%x ====================\n", gain, out, in, option); + + /* Determine REQUESTs */ + switch (gain) { + case AVSYS_AUDIO_GAIN_EX_KEYTONE: + case AVSYS_AUDIO_GAIN_EX_ALARMTONE: + case AVSYS_AUDIO_GAIN_EX_AUDIOPLAYER: + case AVSYS_AUDIO_GAIN_EX_VIDEOPLAYER: + case AVSYS_AUDIO_GAIN_EX_CAMERA: + case AVSYS_AUDIO_GAIN_EX_GAME: + req_gain.playback = AVSYS_AUDIO_PLAYBACK_GAIN_AP; + break; + + case AVSYS_AUDIO_GAIN_EX_RINGTONE: + case AVSYS_AUDIO_GAIN_EX_CALLTONE: + req_gain.playback = AVSYS_AUDIO_PLAYBACK_GAIN_CALLALERT; + break; + + case AVSYS_AUDIO_GAIN_EX_VOICEREC: + case AVSYS_AUDIO_GAIN_EX_CAMCORDER: + req_gain.capture = AVSYS_AUDIO_CAPTURE_GAIN_AP; + break; + + case AVSYS_AUDIO_GAIN_EX_VOICECALL: + req_gain.playback = AVSYS_AUDIO_PLAYBACK_GAIN_VOICECALL; + req_gain.capture = AVSYS_AUDIO_CAPTURE_GAIN_VOICECALL; + if (out == AVSYS_AUDIO_PATH_EX_NONE && in == AVSYS_AUDIO_PATH_EX_NONE) + req_release_path = 1; + break; + + case AVSYS_AUDIO_GAIN_EX_VIDEOCALL: + req_gain.playback = AVSYS_AUDIO_PLAYBACK_GAIN_VIDEOCALL; + req_gain.capture = AVSYS_AUDIO_CAPTURE_GAIN_VIDEOCALL; + if (out == AVSYS_AUDIO_PATH_EX_NONE && in == AVSYS_AUDIO_PATH_EX_NONE) + req_release_path = 1; + break; + + case AVSYS_AUDIO_GAIN_EX_FMRADIO: + req_gain.playback = AVSYS_AUDIO_PLAYBACK_GAIN_FMRADIO; + req_gain.capture = AVSYS_AUDIO_CAPTURE_GAIN_FMRADIO; + if (out == AVSYS_AUDIO_PATH_EX_NONE && in == AVSYS_AUDIO_PATH_EX_NONE) + req_release_path = 1; + break; + } + + /* Get avsys shared memeory */ + temp = &control; + if (AVSYS_FAIL(avsys_audio_get_shm(AVSYS_AUDIO_SHM_IDEN_PATH, (void **)temp))) { + avsys_error_r(AVAUDIO, "avsys_audio_get_shm() failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } + /* LOCK */ + if (AVSYS_FAIL(avsys_audio_lock_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))) { + avsys_error_r(AVAUDIO, "avsys_audio_lock_sync() failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } + + current_pid = getpid(); /* moved from below */ + + /* Check FORCED option */ + if (option & AVSYS_AUDIO_PATH_OPTION_FORCED) { + DO_IF_VALID(req_gain.playback, local_gain.playback = req_gain.playback) + DO_IF_VALID(req_gain.capture, local_gain.capture = req_gain.capture) + } else { + DO_IF_VALID(req_gain.playback, local_gain.playback = g_playback_gain_select_data[control->gain.playback][req_gain.playback]) + DO_IF_VALID(req_gain.capture, local_gain.capture = g_capture_gain_select_data[control->gain.capture][req_gain.capture]) + } + + avsys_info(AVAUDIO, "Gain : req(%d,%d) local(%d,%d)\n", req_gain.playback, req_gain.capture, local_gain.playback, local_gain.capture); + + /* Check path fixed process alive. */ + if (control->path_fixed & PATH_FIXED_WITH_CALL) { + if (AVSYS_FAIL(avsys_check_process(control->path_fixed_pid[PATH_FIXED_TYPE_CALL]))) { + control->path_fixed &= ~PATH_FIXED_WITH_CALL; + } + } + if (control->path_fixed & PATH_FIXED_WITH_FMRADIO) { + if (AVSYS_FAIL(avsys_check_process(control->path_fixed_pid[PATH_FIXED_TYPE_FMRADIO]))) { + control->path_fixed &= ~PATH_FIXED_WITH_FMRADIO; + } + } + if (control->path_fixed == PATH_FIXED_NONE) { + /* forced gain setting when path fixed by dead process */ + if (req_gain.playback != local_gain.playback) { + local_gain.playback = req_gain.playback; + } + if (req_gain.capture != local_gain.capture) { + local_gain.capture = req_gain.capture; + } + } + + if (CHECK_VALID(local_gain.playback)) { + if (g_playback_path_select_data[local_gain.playback][out] == 0) { + avsys_error(AVAUDIO, "[PLAYBACK] Does not support request sound path : conv gain %d, out path %d\n", local_gain.playback, out); + if (AVSYS_FAIL(avsys_audio_unlock_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))) { + avsys_error_r(AVAUDIO, "avsys_audio_unlock_sync() failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } + return AVSYS_STATE_ERR_INVALID_STATE; + } + } + if (CHECK_VALID(local_gain.capture)) { + if (g_capture_path_select_data[local_gain.capture][in] == 0) { + avsys_error(AVAUDIO, "[CAPTURE] Does not support request sound path : conv gain %d, in path %d\n", local_gain.capture, in); + if (AVSYS_FAIL(avsys_audio_unlock_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))) { + avsys_error_r(AVAUDIO, "avsys_audio_unlock_sync() failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } + return AVSYS_STATE_ERR_INVALID_STATE; + } + } + /* overwrite local_gain with current gain if it is simplex sound path */ + DO_IF_INVALID(local_gain.playback, local_gain.playback = control->gain.playback) + DO_IF_INVALID(local_gain.capture, local_gain.capture = control->gain.capture) + control->pregain = control->gain; + control->gain = local_gain; + + DO_IF_VALID(req_gain.playback, control->reqgain.playback = req_gain.playback) + DO_IF_VALID(req_gain.capture, control->reqgain.capture = req_gain.capture) + DO_IF_VALID(local_gain.playback, control->option.playback = option) + DO_IF_VALID(local_gain.capture, control->option.capture = option) + + /* Check for Release PATH */ + if (req_release_path && (req_gain.playback == local_gain.playback) && (req_gain.capture == local_gain.capture)) { + avsys_warning(AVAUDIO,"Release path for %d %d\n", local_gain.playback, local_gain.capture); + + err = __avsys_audio_release_path(local_gain, control); + goto FINISHED; + } + if (CHECK_VALID(req_gain.playback)) { + if(req_gain.playback != local_gain.playback) { + avsys_warning(AVAUDIO, "Sound Path is protected. use current configuration (playback_gain %d, out %d, opt 0x%x)\n", + local_gain.playback, control->path.playback, control->option.playback); + if (req_gain.playback == AVSYS_AUDIO_PLAYBACK_GAIN_AP) { + control->backup_gain.playback = control->reqgain.playback; + control->backup_path.playback = out; + } + } else { + control->path.playback = out; + control->backup_gain.playback = local_gain.playback; + control->backup_path.playback = out; + + switch (local_gain.playback) { + case AVSYS_AUDIO_PLAYBACK_GAIN_VIDEOCALL: + control->path_fixed_pid[PATH_FIXED_TYPE_CALL] = current_pid; + case AVSYS_AUDIO_PLAYBACK_GAIN_CALLALERT: + if (control->path.playback == AVSYS_AUDIO_PATH_EX_BTHEADSET) { + SET_AIF(AIF3_PLAYBACK); + SET_AIF(AIF3_CAPTURE); + } + break; + + case AVSYS_AUDIO_PLAYBACK_GAIN_VOICECALL: + control->path_fixed_pid[PATH_FIXED_TYPE_CALL] = current_pid; + SET_AIF(AIF2_PLAYBACK); + + if (control->path.playback == AVSYS_AUDIO_PATH_EX_BTHEADSET) { + SET_AIF(AIF3_PLAYBACK); + } + break; + + case AVSYS_AUDIO_PLAYBACK_GAIN_FMRADIO: + control->path_fixed_pid[PATH_FIXED_TYPE_FMRADIO] = current_pid; + break; + } + } + } + + if (CHECK_VALID(req_gain.capture)) { + if (req_gain.capture != local_gain.capture) { + avsys_warning(AVAUDIO, "Sound Path is protected. use current configuration (capture_gain %d, in %d, opt 0x%x)\n", + local_gain.capture, control->path.capture, control->option.capture); + if (req_gain.capture == AVSYS_AUDIO_CAPTURE_GAIN_AP) { + control->backup_gain.capture = control->reqgain.capture; + control->backup_path.capture = in; + } + } else { + control->path.capture = in; + control->backup_gain.capture = local_gain.capture; + control->backup_path.capture = in; + + switch (local_gain.capture) { + case AVSYS_AUDIO_CAPTURE_GAIN_VIDEOCALL: + control->path_fixed_pid[PATH_FIXED_TYPE_CALL] = current_pid; + if (control->path.capture == AVSYS_AUDIO_PATH_EX_BTMIC) { + SET_AIF(AIF3_CAPTURE); + } + break; + + case AVSYS_AUDIO_CAPTURE_GAIN_VOICECALL: + control->path_fixed_pid[PATH_FIXED_TYPE_CALL] = current_pid; + SET_AIF(AIF2_CAPTURE); + + if (control->path.capture == AVSYS_AUDIO_PATH_EX_BTMIC) { + SET_AIF(AIF3_CAPTURE); + } + break; + + case AVSYS_AUDIO_CAPTURE_GAIN_FMRADIO: + control->path_fixed_pid[PATH_FIXED_TYPE_FMRADIO] = current_pid; + break; + } + } + } + + /* Open AIFs */ + /* FIXME: this will be moved to after alsa scenraio set */ +#ifdef OPEN_AIF_BEFORE_SCENARIO_SET + err = __avsys_open_aif(AIF_control); +#endif + + /* Do ALSA scenario control based on gain */ + /* Playback */ + if (local_gain.playback == AVSYS_AUDIO_PLAYBACK_GAIN_AP) { + avsys_warning(AVAUDIO, "playback gain : ap\n"); + err = __avsys_audio_path_set_ascn_ap_playback(control); + if (AVSYS_SUCCESS(err)) { + err = __avsys_audio_path_set_hw_controls(control); + } + } else if(local_gain.playback == AVSYS_AUDIO_PLAYBACK_GAIN_CALLALERT) { + avsys_warning(AVAUDIO,"playback gain : callalert\n"); + err = __avsys_audio_path_set_ascn_ap_playback(control); + if (AVSYS_SUCCESS(err)) { + err = __avsys_audio_path_set_hw_controls(control); + } + } else if (local_gain.playback == AVSYS_AUDIO_PLAYBACK_GAIN_FMRADIO && + local_gain.capture == AVSYS_AUDIO_CAPTURE_GAIN_FMRADIO) { + avsys_warning(AVAUDIO, "fmradio gain\n"); + err = __avsys_audio_path_set_ascn_fmradio(control); + } else if (local_gain.playback == AVSYS_AUDIO_PLAYBACK_GAIN_VOICECALL && + local_gain.capture == AVSYS_AUDIO_CAPTURE_GAIN_VOICECALL) { + avsys_warning(AVAUDIO, "voicecall gain\n"); + err = __avsys_audio_path_set_ascn_voicecall(control); + } else if (local_gain.playback == AVSYS_AUDIO_PLAYBACK_GAIN_VIDEOCALL && + local_gain.capture == AVSYS_AUDIO_CAPTURE_GAIN_VIDEOCALL) { + avsys_warning(AVAUDIO, "videocall gain\n"); + err = __avsys_audio_path_set_ascn_videocall(control); + } + /* Capture */ + if (local_gain.capture == AVSYS_AUDIO_CAPTURE_GAIN_AP) { + avsys_warning(AVAUDIO, "capture gain : ap\n"); + err = __avsys_audio_path_set_ascn_ap_capture(control); + } +#ifndef OPEN_AIF_BEFORE_SCENARIO_SET + err = __avsys_open_aif(AIF_control); +#endif + +FINISHED: + /* UnLOCK */ + if (AVSYS_FAIL(avsys_audio_unlock_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))) { + avsys_error_r(AVAUDIO, "avsys_audio_unlock_sync() failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } + avsys_info(AVAUDIO, "------------------------------------------------\n"); + return err; +} + +int avsys_audio_path_ex_get_path(int *gain, int *out, int *in, int *option) +{ + avsys_audio_path_ex_info_t *control = NULL; + avsys_audio_path_ex_info_t ** temp = NULL; + + if(gain == NULL || out == NULL || in == NULL || option == NULL) { + avsys_error(AVAUDIO,"Invalid parameter\n"); + return AVSYS_STATE_ERR_NULL_POINTER; + } + + temp = &control; + + if (AVSYS_FAIL(avsys_audio_get_shm(AVSYS_AUDIO_SHM_IDEN_PATH, (void **)temp))) { + avsys_error_r(AVAUDIO, "avsys_audio_get_shm() failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } + if (AVSYS_FAIL(avsys_audio_lock_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))) { + avsys_error_r(AVAUDIO, "avsys_audio_lock_sync() failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } + + switch (control->gain.playback) { + case AVSYS_AUDIO_PLAYBACK_GAIN_AP: + *gain = AVSYS_AUDIO_GAIN_EX_KEYTONE; + *out = control->path.playback; + *in = AVSYS_AUDIO_PATH_EX_NONE; + *option = control->option.playback; + break; + case AVSYS_AUDIO_PLAYBACK_GAIN_CALLALERT: + *gain = AVSYS_AUDIO_GAIN_EX_RINGTONE; + *out = control->path.playback; + *in = AVSYS_AUDIO_PATH_EX_NONE; + *option = control->option.playback; + break; + case AVSYS_AUDIO_PLAYBACK_GAIN_VOICECALL: + *gain = AVSYS_AUDIO_GAIN_EX_VOICECALL; + *out = control->path.playback; + *in = control->path.capture; + *option = control->option.playback; + break; + case AVSYS_AUDIO_PLAYBACK_GAIN_VIDEOCALL: + *gain = AVSYS_AUDIO_GAIN_EX_VIDEOCALL; + *out = control->path.playback; + *in = control->path.capture; + *option = control->option.playback; + break; + case AVSYS_AUDIO_PLAYBACK_GAIN_FMRADIO: + *gain = AVSYS_AUDIO_GAIN_EX_FMRADIO; + *out = control->path.playback; + *in = control->path.capture; + *option = control->option.playback; + break; + } + + if (AVSYS_FAIL(avsys_audio_unlock_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))) { + avsys_error_r(AVAUDIO, "avsys_audio_unlock_sync() failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } + + return AVSYS_STATE_SUCCESS; +} + +int avsys_audio_path_ex_set_amp(const int onoff) +{ + //not yet implemented. + return AVSYS_STATE_SUCCESS; +} + +int avsys_audio_path_ex_set_mute(const int mute) +{ + avsys_audio_path_ex_info_t *control = NULL; + avsys_audio_path_ex_info_t **temp = NULL; + + temp = &control; + + if (AVSYS_FAIL(avsys_audio_get_shm(AVSYS_AUDIO_SHM_IDEN_PATH, (void **)temp))) { + avsys_error_r(AVAUDIO, "avsys_audio_get_shm() failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } + + if (control == NULL) { + return AVSYS_STATE_ERR_NULL_POINTER; + } + + if (mute == AVSYS_AUDIO_UNMUTE || mute == AVSYS_AUDIO_MUTE) { + if (AVSYS_FAIL(avsys_audio_lock_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))) { + avsys_error_r(AVAUDIO, "avsys_audio_lock_sync() failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } + + if (control->mute == mute) { + avsys_info(AVAUDIO, "[Path Mute] skip mute ctrl op: %d\n", mute); + if (AVSYS_FAIL(avsys_audio_unlock_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))) { + avsys_error_r(AVAUDIO, "avsys_audio_unlock_sync() 2 failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } + return AVSYS_STATE_SUCCESS; + } else { + control->mute = mute; + avsys_warning(AVAUDIO, "[Path Mute] run mute ctrl op: %d\n", mute); + } + + if (control->mute) { + if (AVSYS_FAIL(avsys_audio_ascn_single_set(ASCN_STR_PLAYBACK_MUTE))) { + if (AVSYS_FAIL(avsys_audio_unlock_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))) { + avsys_error_r(AVAUDIO, "avsys_audio_unlock_sync() 1 failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } + avsys_error(AVAUDIO, "Mute fail %s\n", __func__); + return AVSYS_STATE_ERR_IO_CONTROL; + } + } else { + if (AVSYS_FAIL(avsys_audio_ascn_single_set(ASCN_STR_PLAYBACK_UNMUTE))) { + if (AVSYS_FAIL(avsys_audio_unlock_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))) { + avsys_error_r(AVAUDIO, "avsys_audio_unlock_sync() 1 failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } + avsys_error(AVAUDIO, "Unmute fail %s\n", __func__); + return AVSYS_STATE_ERR_IO_CONTROL; + } + } + + if (AVSYS_FAIL(avsys_audio_unlock_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))) { + avsys_error_r(AVAUDIO, "avsys_audio_unlock_sync() 2 failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } + } else { + int mute_nolock; + if (mute == AVSYS_AUDIO_UNMUTE_NOLOCK) /* set nomalize */ + mute_nolock = AVSYS_AUDIO_UNMUTE; + else + mute_nolock = AVSYS_AUDIO_MUTE; + + if (control->mute == mute_nolock) { + avsys_info(AVAUDIO, "[Path Mute] skip mute ctrl op: %d\n", mute); + return AVSYS_STATE_SUCCESS; + } else { + control->mute = mute_nolock; + avsys_warning(AVAUDIO, "[Path Mute] run mute ctrl op: %d\n", mute); + } + + if (control->mute) { + if (AVSYS_FAIL(avsys_audio_ascn_single_set(ASCN_STR_PLAYBACK_MUTE))) { + avsys_error(AVAUDIO, "Mute fail %s\n", __func__); + return AVSYS_STATE_ERR_IO_CONTROL; + } + } else { + if (AVSYS_FAIL(avsys_audio_ascn_single_set(ASCN_STR_PLAYBACK_UNMUTE))) { + avsys_error(AVAUDIO, "Unmute fail %s\n", __func__); + return AVSYS_STATE_ERR_IO_CONTROL; + } + } + } + + if (mute == AVSYS_AUDIO_UNMUTE || mute == AVSYS_AUDIO_UNMUTE_NOLOCK) + avsys_info_r(AVAUDIO, "Global Mute Disabled\n"); + else if (mute == AVSYS_AUDIO_MUTE || mute == AVSYS_AUDIO_MUTE_NOLOCK) + avsys_info_r(AVAUDIO, "Global Mute Enabled\n"); + return AVSYS_STATE_SUCCESS; +} + +int avsys_audio_path_ex_get_mute(int *mute) +{ + avsys_audio_path_ex_info_t *control = NULL; + avsys_audio_path_ex_info_t **temp = NULL; + + temp = &control; + + if (AVSYS_FAIL(avsys_audio_get_shm(AVSYS_AUDIO_SHM_IDEN_PATH, (void **)temp))) { + avsys_error_r(AVAUDIO, "avsys_audio_get_shm() failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } + + if (control == NULL) { + return AVSYS_STATE_ERR_NULL_POINTER; + } + + if (AVSYS_FAIL(avsys_audio_lock_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))) { + avsys_error_r(AVAUDIO, "avsys_audio_lock_sync() failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } + + *mute = control->mute; + + if (AVSYS_FAIL(avsys_audio_unlock_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))) { + avsys_error_r(AVAUDIO, "avsys_audio_unlock_sync() failed in %s\n", __func__); + return AVSYS_STATE_ERR_INTERNAL; + } + + return AVSYS_STATE_SUCCESS; +} + +static int __avsys_audio_path_set_ascn_ap_playback(avsys_audio_path_ex_info_t *control) +{ + int cmd_gain[2] = { 0, 0 }; + int cmd_path[3] = { 0, 0, 0 }; + char callalert_mode = 0; + + avsys_info(AVAUDIO, "<< path.playback = %d, option = %x, gain.playback = %d, inserted = %d\n", + control->path.playback, control->option.playback, control->gain.playback, control->inserted); + + callalert_mode = (control->gain.playback == AVSYS_AUDIO_PLAYBACK_GAIN_CALLALERT) ? 1 : 0; + control->path_fixed = PATH_FIXED_NONE; + + switch (control->path.playback) { + case AVSYS_AUDIO_PATH_EX_SPK: + if (control->option.playback & AVSYS_AUDIO_PATH_OPTION_LEGACY_MODE) { + avsys_warning(AVAUDIO, "Does not support legacy mode anymore\n"); + } + + if (control->option.playback & AVSYS_AUDIO_PATH_OPTION_DUAL_OUT) { + if (callalert_mode) { + control->gain_status.playback = GS_AP_TO_SPK_CALLALERT; + cmd_gain[0] = INPUT_AP | OUTPUT_STEREO_SPK | GAIN_CALLALERT; + } else { + control->gain_status.playback = GS_AP_TO_SPK; + cmd_gain[0] = INPUT_AP | OUTPUT_STEREO_SPK | GAIN_MODE; + } + + if (control->inserted == AVSYS_AUDIO_INSERTED_NONE) { + control->path_status.playback = PS_AP_TO_SPK; + cmd_path[0] = INPUT_AP | OUTPUT_STEREO_SPK; + } else { + control->path_status.playback = PS_AP_TO_SPK | PS_AP_TO_HEADSET; + cmd_path[0] = INPUT_AP | OUTPUT_STEREO_SPK; + cmd_path[1] = INPUT_AP | OUTPUT_HEADSET; + } + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_SPK; + } else { + if (control->option.playback & AVSYS_AUDIO_PATH_OPTION_JACK_AUTO) { + control->ear_auto = AVSYS_AUDIO_EAR_SWITCH_AUTO_WITH_MUTE; + if (control->inserted == AVSYS_AUDIO_INSERTED_NONE) { + if (callalert_mode) { + control->gain_status.playback = GS_AP_TO_SPK_CALLALERT; + cmd_gain[0] = INPUT_AP | OUTPUT_STEREO_SPK | GAIN_CALLALERT; + } else { + control->gain_status.playback = GS_AP_TO_SPK; + cmd_gain[0] = INPUT_AP | OUTPUT_STEREO_SPK | GAIN_MODE; + } + control->path_status.playback = PS_AP_TO_SPK; + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_SPK; + cmd_path[0] = INPUT_AP | OUTPUT_STEREO_SPK; + } else { + if (callalert_mode) { + control->gain_status.playback = GS_AP_TO_HEADSET_CALLALERT; + cmd_gain[0] = INPUT_AP | OUTPUT_HEADSET | GAIN_CALLALERT; + } else { + control->gain_status.playback = GS_AP_TO_HEADSET; + cmd_gain[0] = INPUT_AP | OUTPUT_HEADSET | GAIN_MODE; + } + control->path_status.playback = PS_AP_TO_HEADSET; + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_HEADSET; + cmd_path[0] = INPUT_AP | OUTPUT_HEADSET; + } + } else { + if (callalert_mode) { + control->gain_status.playback = GS_AP_TO_SPK_CALLALERT; + cmd_gain[0] = INPUT_AP | OUTPUT_STEREO_SPK | GAIN_CALLALERT; + } else { + control->gain_status.playback = GS_AP_TO_SPK; + cmd_gain[0] = INPUT_AP | OUTPUT_STEREO_SPK | GAIN_MODE; + } + control->ear_auto = AVSYS_AUDIO_EAR_SWITCH_AUTO_WITHOUT_MUTE; + control->path_status.playback = PS_AP_TO_SPK; + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_SPK; + + cmd_path[0] = INPUT_AP | OUTPUT_STEREO_SPK; + } + } + break; + + case AVSYS_AUDIO_PATH_EX_RECV: + if (control->option.playback & AVSYS_AUDIO_PATH_OPTION_LEGACY_MODE) { + avsys_warning(AVAUDIO, "Does not support legacy mode anymore\n"); + } + + if (control->option.playback & AVSYS_AUDIO_PATH_OPTION_JACK_AUTO) { + control->ear_auto = AVSYS_AUDIO_EAR_SWITCH_AUTO_WITH_MUTE; + if (control->inserted == AVSYS_AUDIO_INSERTED_NONE) { + control->gain_status.playback = GS_AP_TO_RECV; + control->path_status.playback = PS_AP_TO_RECV; + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_SPK; + cmd_gain[0] = INPUT_AP | OUTPUT_RECV | GAIN_MODE; + cmd_path[0] = INPUT_AP | OUTPUT_RECV; + } else { + if (callalert_mode) { + control->gain_status.playback = GS_AP_TO_HEADSET_CALLALERT; + cmd_gain[0] = INPUT_AP | OUTPUT_HEADSET | GAIN_CALLALERT; + } else { + control->gain_status.playback = GS_AP_TO_HEADSET; + cmd_gain[0] = INPUT_AP | OUTPUT_HEADSET | GAIN_MODE; + } + control->path_status.playback = PS_AP_TO_HEADSET; + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_HEADSET; + cmd_path[0] = INPUT_AP | OUTPUT_HEADSET; + } + } else { + control->ear_auto = AVSYS_AUDIO_EAR_SWITCH_MANUAL; + control->gain_status.playback = GS_AP_TO_RECV; + control->path_status.playback = PS_AP_TO_RECV; + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_SPK; + cmd_gain[0] = INPUT_AP | OUTPUT_RECV | GAIN_MODE; + cmd_path[0] = INPUT_AP | OUTPUT_RECV; + } + break; + + case AVSYS_AUDIO_PATH_EX_HEADSET: + control->ear_auto = AVSYS_AUDIO_EAR_SWITCH_MANUAL; + if (callalert_mode) { + control->gain_status.playback = GS_AP_TO_HEADSET_CALLALERT; + cmd_gain[0] = INPUT_AP | OUTPUT_HEADSET | GAIN_CALLALERT; + } else { + control->gain_status.playback = GS_AP_TO_HEADSET; + cmd_gain[0] = INPUT_AP | OUTPUT_HEADSET | GAIN_MODE; + } + control->path_status.playback = PS_AP_TO_HEADSET; + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_HEADSET; + cmd_path[0] = INPUT_AP | OUTPUT_HEADSET; + break; + + case AVSYS_AUDIO_PATH_EX_HDMI: + avsys_warning(AVAUDIO, "Does not support dedicated HDMI sound path\n"); + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_SPK; + break; + + case AVSYS_AUDIO_PATH_EX_BTHEADSET: + control->ear_auto = AVSYS_AUDIO_EAR_SWITCH_MANUAL; + control->gain_status.playback = GS_AP_TO_BT; + control->path_status.playback = PS_AP_TO_BT; + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_BTHEADSET; + cmd_gain[0] = INPUT_AP | OUTPUT_BT_HEADSET | GAIN_MODE; + cmd_path[0] = INPUT_AP | OUTPUT_BT_HEADSET; + break; + case AVSYS_AUDIO_PATH_EX_HANDSFREE: + default: /* DEFAULT PATH CONTROL TO NONE */ + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_SPK; + break; + } + + //avsys_warning(AVAUDIO,"pg(0x%X), g(0x%X), pp(0x%X), p(0x%X)\n", control->p_gain_status, control->gain_status, control->p_path_status, control->path_status); + if ((control->p_path_status.playback != control->path_status.playback) || control->gain_debug_mode == 1) { + avsys_warning(AVAUDIO, "Run Alsa Scenario Script\n"); + RET_IO_CTL_ERR_IF_FAIL(avsys_audio_ascn_bulk_set(cmd_gain, 1, ASCN_RESET_PLAYBACK)) + control->p_gain_status.playback = control->gain_status.playback; + RET_IO_CTL_ERR_IF_FAIL(avsys_audio_ascn_bulk_set(cmd_path, 2, ASCN_RESET_NONE)) + control->p_path_status.playback = control->path_status.playback; + } + + avsys_info(AVAUDIO, ">> leave"); + return AVSYS_STATE_SUCCESS; +} + +static int __avsys_audio_path_set_ascn_voicecall(avsys_audio_path_ex_info_t *control) +{ + return AVSYS_STATE_SUCCESS; +} + +static int __avsys_audio_path_set_ascn_videocall(avsys_audio_path_ex_info_t *control) +{ + int cmd_gain[2] = { 0, 0 }; + int cmd_path[3] = { 0, 0, 0 }; + int skip_clear = 0; + control->path_fixed = PATH_FIXED_WITH_CALL; + switch (control->path.playback) { + case AVSYS_AUDIO_PATH_EX_NONE: + if (control->option.playback & AVSYS_AUDIO_PATH_OPTION_LEGACY_MODE) { + /* Legacy mode does not effect here... */ + avsys_warning(AVAUDIO, "legacy mode option %s\n", __func__); + } + control->ear_auto = AVSYS_AUDIO_EAR_SWITCH_MANUAL; + if (control->reqgain.playback == control->gain.playback) { + avsys_warning(AVAUDIO, "Output block on videocall"); + } else { + avsys_warning(AVAUDIO, "Ignore another path setting request during voicecall"); + } + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_SPK; + break; + + case AVSYS_AUDIO_PATH_EX_SPK: + if (control->reqgain.playback == control->gain.playback) { + if (control->option.playback & AVSYS_AUDIO_PATH_OPTION_JACK_AUTO) { + control->ear_auto = AVSYS_AUDIO_EAR_SWITCH_AUTO_WITH_MUTE; + if (control->inserted != AVSYS_AUDIO_INSERTED_NONE) { + control->gain_status.playback = GS_AP_TO_HEADSET; + control->path_status.playback = PS_AP_TO_HEADSET; + cmd_gain[0] = INPUT_AP | OUTPUT_HEADSET | GAIN_MODE; + cmd_path[0] = INPUT_AP | OUTPUT_HEADSET; + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_HEADSET; + } else { + control->gain_status.playback = GS_AP_TO_SPK; + control->path_status.playback = PS_AP_TO_SPK; + cmd_gain[0] = INPUT_AP | OUTPUT_STEREO_SPK | GAIN_MODE; + cmd_path[0] = INPUT_AP | OUTPUT_STEREO_SPK; + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_SPK; + } + } else { /* ear jack manual */ + control->ear_auto = AVSYS_AUDIO_EAR_SWITCH_MANUAL; + control->gain_status.playback = GS_AP_TO_SPK; + control->path_status.playback = PS_AP_TO_SPK; + cmd_gain[0] = INPUT_AP | OUTPUT_STEREO_SPK | GAIN_MODE; + cmd_path[0] = INPUT_AP | OUTPUT_STEREO_SPK; + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_SPK; + } + } else { /* changed by priority */ + avsys_warning(AVAUDIO, "Sound Path request during VT call ignored."); + } + break; + + case AVSYS_AUDIO_PATH_EX_RECV: + if (control->gain.playback == control->reqgain.playback) { + if (control->option.playback & AVSYS_AUDIO_PATH_OPTION_JACK_AUTO) { + control->ear_auto = AVSYS_AUDIO_EAR_SWITCH_AUTO_WITH_MUTE; + if (control->inserted != AVSYS_AUDIO_INSERTED_NONE) { + control->gain_status.playback = GS_AP_TO_HEADSET; + control->path_status.playback = PS_AP_TO_HEADSET; + cmd_gain[0] = INPUT_AP | OUTPUT_HEADSET | GAIN_MODE; + cmd_path[0] = INPUT_AP | OUTPUT_HEADSET; + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_HEADSET; + } else { + control->gain_status.playback = GS_AP_TO_RECV; + control->path_status.playback = PS_AP_TO_RECV; + cmd_gain[0] = INPUT_AP | OUTPUT_RECV | GAIN_MODE; + cmd_path[0] = INPUT_AP | OUTPUT_RECV; + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_SPK; + } + } else { /* ear jack manual */ + control->ear_auto = AVSYS_AUDIO_EAR_SWITCH_MANUAL; + control->gain_status.playback = GS_AP_TO_RECV; + control->path_status.playback = PS_AP_TO_RECV; + cmd_gain[0] = INPUT_AP | OUTPUT_RECV | GAIN_MODE; + cmd_path[0] = INPUT_AP | OUTPUT_RECV; + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_SPK; + } + } else { /* changed by priority */ + avsys_warning(AVAUDIO, "Sound Path request during VT call ignored."); + } /* reqgain, gain */ + break; + + case AVSYS_AUDIO_PATH_EX_HEADSET: + if (control->reqgain.playback == control->gain.playback) { + control->ear_auto = AVSYS_AUDIO_EAR_SWITCH_MANUAL; + control->gain_status.playback = GS_AP_TO_HEADSET; + control->path_status.playback = PS_AP_TO_HEADSET; + cmd_gain[0] = INPUT_AP | OUTPUT_HEADSET | GAIN_MODE; + cmd_path[0] = INPUT_AP | OUTPUT_HEADSET; + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_HEADSET; + } else { + avsys_warning(AVAUDIO, "Sound Path request during VT call ignored."); + } + break; + + case AVSYS_AUDIO_PATH_EX_BTHEADSET: + if (control->reqgain.playback == control->gain.playback) { + control->ear_auto = AVSYS_AUDIO_EAR_SWITCH_MANUAL; + control->gain_status.playback = GS_AP_TO_BT; + control->path_status.playback = PS_AP_TO_BT; + cmd_gain[0] = INPUT_AP | OUTPUT_BT_HEADSET | GAIN_MODE; + cmd_path[0] = INPUT_AP | OUTPUT_BT_HEADSET; + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_BTHEADSET; + } else { + avsys_warning(AVAUDIO, "Sound Path request during VT call ignored."); + } + break; + + case AVSYS_AUDIO_PATH_EX_HANDSFREE: + default: + if (control->reqgain.playback == control->gain.playback) { + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_SPK; + } + break; + } + + switch (control->path.capture) { + case AVSYS_AUDIO_PATH_EX_NONE: + if (control->reqgain.capture == control->gain.capture) { + /* Clear modem input */ + control->path_status.capture &= ~(PS_MAINMIC_TO_AP | PS_SUBMIC_TO_AP | PS_EARMIC_TO_AP | PS_BTMIC_TO_AP); + } else { + avsys_warning(AVAUDIO, "Ignore another path setting request during VT call (input)\n"); + } + break; + + case AVSYS_AUDIO_PATH_EX_MIC: + if (control->option.capture & AVSYS_AUDIO_PATH_OPTION_JACK_AUTO) { + if ((control->inserted == AVSYS_AUDIO_INSERTED_4) && (control->path_status.playback & PS_AP_TO_HEADSET)) { + control->gain_status.capture |= GS_EARMIC_TO_AP; + control->path_status.capture |= PS_EARMIC_TO_AP; + cmd_gain[1] = INPUT_EAR_MIC | OUTPUT_AP | GAIN_MODE; + cmd_path[1] = INPUT_EAR_MIC | OUTPUT_AP; + } else { + if (control->option.capture & AVSYS_AUDIO_PATH_OPTION_USE_SUBMIC) { + control->gain_status.capture |= GS_SUBMIC_TO_AP; + control->path_status.capture |= PS_SUBMIC_TO_AP; + cmd_gain[1] = INPUT_SUB_MIC | OUTPUT_AP | GAIN_MODE; + cmd_path[1] = INPUT_SUB_MIC | OUTPUT_AP; + } else { + control->gain_status.capture |= GS_MAINMIC_TO_AP; + control->path_status.capture |= PS_MAINMIC_TO_AP; + cmd_gain[1] = INPUT_MAIN_MIC | OUTPUT_AP | GAIN_MODE; + cmd_path[1] = INPUT_MAIN_MIC | OUTPUT_AP; + } + } + } else { + if (control->option.capture & AVSYS_AUDIO_PATH_OPTION_USE_SUBMIC) { + control->gain_status.capture |= GS_SUBMIC_TO_AP; + control->path_status.capture |= PS_SUBMIC_TO_AP; + cmd_gain[1] = INPUT_SUB_MIC | OUTPUT_AP | GAIN_MODE; + cmd_path[1] = INPUT_SUB_MIC | OUTPUT_AP; + } else { + control->gain_status.capture |= GS_MAINMIC_TO_AP; + control->path_status.capture |= PS_MAINMIC_TO_AP; + cmd_gain[1] = INPUT_MAIN_MIC | OUTPUT_AP | GAIN_MODE; + cmd_path[1] = INPUT_MAIN_MIC | OUTPUT_AP; + } + } + break; + + case AVSYS_AUDIO_PATH_EX_HEADSETMIC: + control->gain_status.capture |= GS_EARMIC_TO_AP; + control->path_status.capture |= PS_EARMIC_TO_AP; + cmd_gain[1] = INPUT_EAR_MIC | OUTPUT_AP | GAIN_MODE; + cmd_path[1] = INPUT_EAR_MIC | OUTPUT_AP; + break; + + case AVSYS_AUDIO_PATH_EX_BTMIC: + control->gain_status.capture |= GS_BTMIC_TO_AP; + control->path_status.capture |= PS_BTMIC_TO_AP; + cmd_gain[1] = INPUT_BT_MIC | OUTPUT_AP | GAIN_MODE; + cmd_path[1] = INPUT_BT_MIC | OUTPUT_AP; + + break; + case AVSYS_AUDIO_PATH_EX_HANDSFREE: + default: + break; + } + + if((control->p_path_status.playback != control->path_status.playback) + || ((control->p_path_status.capture != control->path_status.capture)) || control->gain_debug_mode == 1) { + if(!skip_clear) { + RET_IO_CTL_ERR_IF_FAIL(avsys_audio_ascn_single_set(ASCN_STR_RESET)) + } + RET_IO_CTL_ERR_IF_FAIL(avsys_audio_ascn_bulk_set(cmd_gain, 2, ASCN_RESET_NONE)) + control->p_gain_status = control->gain_status; /* both playback and capture */ + RET_IO_CTL_ERR_IF_FAIL(avsys_audio_ascn_bulk_set(cmd_path, 2, ASCN_RESET_NONE)) + control->p_path_status = control->path_status; /* both playback and capture */ + } + + return AVSYS_STATE_SUCCESS; +} + + +static int __avsys_audio_path_set_ascn_fmradio(avsys_audio_path_ex_info_t *control) +{ + int cmd_gain[2] = { 0, 0 }; + int cmd_path[3] = { 0, 0, 0 }; + int skip_clear = 0; + int skip_clear_record = 0; + int gain_idx = 0; + int path_idx = 0; + control->path_fixed = PATH_FIXED_WITH_FMRADIO; + switch (control->path.playback) { + case AVSYS_AUDIO_PATH_EX_NONE: + control->ear_auto = AVSYS_AUDIO_EAR_SWITCH_MANUAL; + control->gain_status.playback = GS_FMRADIO_TO_SPK; + control->path_status.playback = PS_PATH_NONE; + cmd_gain[gain_idx++] = INPUT_FMRADIO | OUTPUT_STEREO_SPK | GAIN_MODE; + break; + + case AVSYS_AUDIO_PATH_EX_SPK: + if (control->option.playback & AVSYS_AUDIO_PATH_OPTION_JACK_AUTO) { + control->ear_auto = AVSYS_AUDIO_EAR_SWITCH_AUTO_WITHOUT_MUTE; + if (control->reqgain.playback == control->gain.playback) { + if (control->inserted != AVSYS_AUDIO_INSERTED_NONE) { + control->gain_status.playback = GS_FMRADIO_TO_HEADSET; + control->path_status.playback = PS_FMRADIO_TO_HEADSET; + cmd_gain[gain_idx++] = INPUT_FMRADIO | OUTPUT_HEADSET | GAIN_MODE; + cmd_path[path_idx++] = INPUT_FMRADIO | OUTPUT_HEADSET; + cmd_path[path_idx++] = INPUT_AP | OUTPUT_HEADSET; + } else { + control->gain_status.playback = GS_FMRADIO_TO_SPK; + control->path_status.playback = PS_FMRADIO_TO_SPK; + cmd_gain[gain_idx++] = INPUT_FMRADIO | OUTPUT_STEREO_SPK | GAIN_MODE; + cmd_path[path_idx++] = INPUT_FMRADIO | OUTPUT_STEREO_SPK; + cmd_path[path_idx++] = INPUT_AP | OUTPUT_STEREO_SPK; + } + } else { + /* append ap playback sound path */ + control->path_status.playback = control->p_path_status.playback; + if (control->inserted != AVSYS_AUDIO_INSERTED_NONE) { + control->path_status.playback |= PS_AP_TO_HEADSET; + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_HEADSET; + cmd_path[path_idx++] = INPUT_AP | OUTPUT_HEADSET; + } else { + control->path_status.playback |= PS_AP_TO_SPK; + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_SPK; + cmd_path[path_idx++] = INPUT_AP | OUTPUT_STEREO_SPK; + } + skip_clear = 1; + } + } else { /* ear jack manual */ + control->ear_auto = AVSYS_AUDIO_EAR_SWITCH_MANUAL; + if (control->reqgain.playback == control->gain.playback) { + control->gain_status.playback = GS_FMRADIO_TO_SPK; + control->path_status.playback = PS_FMRADIO_TO_SPK; + cmd_gain[gain_idx++] = INPUT_FMRADIO | OUTPUT_STEREO_SPK | GAIN_MODE; + cmd_path[path_idx++] = INPUT_FMRADIO | OUTPUT_STEREO_SPK; + cmd_path[path_idx++] = INPUT_AP | OUTPUT_STEREO_SPK; + } else { + /* append ap playback sound path */ + control->path_status.playback = control->p_path_status.playback; + control->path_status.playback |= PS_AP_TO_SPK; + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_SPK; + cmd_path[path_idx++] = INPUT_AP | OUTPUT_STEREO_SPK; + skip_clear = 1; + } + } + break; + + case AVSYS_AUDIO_PATH_EX_HEADSET: + control->ear_auto = AVSYS_AUDIO_EAR_SWITCH_MANUAL; + if (control->reqgain.playback == control->gain.playback) { + control->gain_status.playback = GS_FMRADIO_TO_HEADSET; + control->path_status.playback = PS_FMRADIO_TO_HEADSET; + cmd_gain[gain_idx++] = INPUT_FMRADIO | OUTPUT_HEADSET | GAIN_MODE; + cmd_path[path_idx++] = INPUT_FMRADIO | OUTPUT_HEADSET; + cmd_path[path_idx++] = INPUT_AP | OUTPUT_HEADSET; + } else { + /* append ap playback */ + control->path_status.playback = control->p_path_status.playback; + control->path_status.playback |= PS_AP_TO_HEADSET; + control->lvol_dev_type = AVSYS_AUDIO_LVOL_DEV_TYPE_HEADSET; + cmd_path[path_idx++] = INPUT_AP | OUTPUT_HEADSET; + skip_clear = 1; + } + break; + default: + break; + } + + switch (control->path.capture) { + case AVSYS_AUDIO_PATH_EX_FMINPUT: + if (control->reqgain.capture == control->gain.capture) { + control->path_status.capture |= PS_FMRADIO_TO_AP; + cmd_path[path_idx++] = INPUT_FMRADIO | OUTPUT_AP; + if (control->reqgain.capture == control->pregain.capture) { + skip_clear_record = 1; + } + } + break; + default: + break; + } + + if((control->p_path_status.playback != control->path_status.playback) + || (control->p_path_status.capture != control->path_status.capture) || control->gain_debug_mode == 1) { + if (skip_clear_record) { + RET_IO_CTL_ERR_IF_FAIL(avsys_audio_ascn_single_set(ASCN_STR_RESET_PLAYBACK)) + } else if (!skip_clear) { + RET_IO_CTL_ERR_IF_FAIL(avsys_audio_ascn_single_set(ASCN_STR_RESET)) + } + RET_IO_CTL_ERR_IF_FAIL(avsys_audio_ascn_bulk_set(cmd_gain, gain_idx, ASCN_RESET_NONE)) + control->p_gain_status = control->gain_status; /* both playback & capture */ + RET_IO_CTL_ERR_IF_FAIL(avsys_audio_ascn_bulk_set(cmd_path, path_idx, ASCN_RESET_NONE)) + control->p_path_status = control->path_status; /* both playback & capture */ + } + + return AVSYS_STATE_SUCCESS; +} + +static int __avsys_audio_path_set_ascn_ap_capture(avsys_audio_path_ex_info_t *control) +{ + int cmd_gain[2] = { 0, 0 }; + int cmd_path[3] = { 0, 0, 0 }; + + avsys_info(AVAUDIO, "<< path.capture = %d, option = %x, gain.capture = %d, inserted = %d\n", + control->path.capture, control->option.capture, control->gain.capture, control->inserted); + switch(control->path.capture) { + case AVSYS_AUDIO_PATH_EX_MIC: + if (control->option.capture & AVSYS_AUDIO_PATH_OPTION_JACK_AUTO) { + control->ear_auto = AVSYS_AUDIO_EAR_SWITCH_AUTO_WITH_MUTE; + if (control->inserted == AVSYS_AUDIO_INSERTED_4) { + control->gain_status.capture = GS_EARMIC_TO_AP; + control->path_status.capture = PS_EARMIC_TO_AP; + cmd_gain[0] = INPUT_EAR_MIC | OUTPUT_AP | GAIN_MODE; + cmd_path[0] = INPUT_EAR_MIC | OUTPUT_AP; + } else { + if (control->option.capture & AVSYS_AUDIO_PATH_OPTION_USE_SUBMIC) { + control->gain_status.capture = GS_SUBMIC_TO_AP; + control->path_status.capture = PS_SUBMIC_TO_AP; + cmd_gain[0] = INPUT_SUB_MIC | OUTPUT_AP | GAIN_MODE; + cmd_path[0] = INPUT_SUB_MIC | OUTPUT_AP; + } else if (control->option.capture & AVSYS_AUDIO_PATH_OPTION_USE_STEREOMIC) { + control->gain_status.capture = GS_STEREOMIC_TO_AP; + control->path_status.capture = PS_STEREOMIC_TO_AP; + cmd_gain[0] = INPUT_STEREO_MIC | OUTPUT_AP | GAIN_MODE; + cmd_path[0] = INPUT_STEREO_MIC | OUTPUT_AP; + } else { + control->gain_status.capture = GS_MAINMIC_TO_AP; + control->path_status.capture = PS_MAINMIC_TO_AP; + cmd_gain[0] = INPUT_MAIN_MIC | OUTPUT_AP | GAIN_MODE; + cmd_path[0] = INPUT_MAIN_MIC | OUTPUT_AP; + } + } + } else { + control->ear_auto = AVSYS_AUDIO_EAR_SWITCH_AUTO_WITHOUT_MUTE; + if (control->option.capture & AVSYS_AUDIO_PATH_OPTION_USE_SUBMIC) { + control->gain_status.capture = GS_SUBMIC_TO_AP; + control->path_status.capture = PS_SUBMIC_TO_AP; + cmd_gain[0] = INPUT_SUB_MIC | OUTPUT_AP | GAIN_MODE; + cmd_path[0] = INPUT_SUB_MIC | OUTPUT_AP; + } else if (control->option.capture & AVSYS_AUDIO_PATH_OPTION_USE_STEREOMIC) { + control->gain_status.capture = GS_STEREOMIC_TO_AP; + control->path_status.capture = PS_STEREOMIC_TO_AP; + cmd_gain[0] = INPUT_STEREO_MIC | OUTPUT_AP | GAIN_MODE; + cmd_path[0] = INPUT_STEREO_MIC | OUTPUT_AP; + } else { + control->gain_status.capture = GS_MAINMIC_TO_AP; + control->path_status.capture = PS_MAINMIC_TO_AP; + cmd_gain[0] = INPUT_MAIN_MIC | OUTPUT_AP | GAIN_MODE; + cmd_path[0] = INPUT_MAIN_MIC | OUTPUT_AP; + } + } + break; + + case AVSYS_AUDIO_PATH_EX_HEADSETMIC: + control->ear_auto = AVSYS_AUDIO_EAR_SWITCH_MANUAL; + control->gain_status.capture = GS_EARMIC_TO_AP; + control->path_status.capture = PS_EARMIC_TO_AP; + cmd_gain[0] = INPUT_EAR_MIC | OUTPUT_AP | GAIN_MODE; + cmd_path[0] = INPUT_EAR_MIC | OUTPUT_AP; + break; + + default: + break; + } + + if ((control->p_path_status.capture != control->path_status.capture) || control->gain_debug_mode == 1) { + RET_IO_CTL_ERR_IF_FAIL(avsys_audio_ascn_bulk_set(cmd_gain, 2, ASCN_RESET_CAPTURE)) + control->p_gain_status.capture = control->gain_status.capture; + RET_IO_CTL_ERR_IF_FAIL(avsys_audio_ascn_bulk_set(cmd_path, 2, ASCN_RESET_NONE)) + control->p_path_status.capture = control->path_status.capture; + } + + avsys_info (AVAUDIO, ">> leave"); + + return AVSYS_STATE_SUCCESS; +} + + +static int __avsys_audio_path_set_hw_controls(avsys_audio_path_ex_info_t *control) +{ + avsys_audio_handle_info_t *handle_control = NULL; + avsys_audio_handle_info_t **temp = NULL; + int ret = AVSYS_STATE_SUCCESS; + avsys_info(AVAUDIO, "global mute %d\n", control->mute); + avsys_info(AVAUDIO, "path_fixed mute %d\n", control->path_fixed); + + /* update logical volume table - about output device - information for open handles */ + avsys_info(AVAUDIO, "Control handle informations\n"); + { + avsys_audio_handle_t *ptr = NULL; + int handle = -1; + int out_device = AVSYS_AUDIO_LVOL_DEV_TYPE_SPK; + + temp = &handle_control; + if (AVSYS_FAIL(avsys_audio_get_shm(AVSYS_AUDIO_SHM_IDEN_HANDLE, (void**)temp))) { + avsys_error(AVAUDIO, "avsys_audio_get_shm() failed in %s\n",__func__); + return AVSYS_STATE_ERR_INTERNAL; + } + + if (AVSYS_FAIL(avsys_audio_lock_sync(AVSYS_AUDIO_SYNC_IDEN_HANDLE))) { + avsys_error(AVAUDIO, "avsys_audio_lock_sync() failed in %s\n",__func__); + return AVSYS_STATE_ERR_INTERNAL; + } + + while (++handle < AVSYS_AUDIO_HANDLE_MAX) { + long long int flag = 0x01; + flag <<= handle; + + if (handle_control->allocated & flag) + { + ptr = &(handle_control->handles[handle]); + + if (ptr->mode != AVSYS_AUDIO_MODE_OUTPUT && ptr->mode != AVSYS_AUDIO_MODE_OUTPUT_CLOCK + && ptr->mode != AVSYS_AUDIO_MODE_OUTPUT_LOW_LATENCY && ptr->mode != AVSYS_AUDIO_MODE_OUTPUT_AP_CALL) { + continue; + } + ptr->path_off = 0; + out_device = control->lvol_dev_type; + if (control->path_status.playback == PS_PATH_NONE) { + ptr->path_off = 1; + avsys_warning(AVAUDIO, "Path off status...set logical volume device type to speaker\n"); + out_device = AVSYS_AUDIO_LVOL_DEV_TYPE_SPK; + } + avsys_audio_logical_volume_update_table(out_device, &ptr->gain_setting); + avsys_audio_logical_volume_convert(&ptr->setting_vol, &ptr->working_vol, &ptr->gain_setting); + } + } + + if(AVSYS_FAIL(avsys_audio_unlock_sync(AVSYS_AUDIO_SYNC_IDEN_HANDLE))) { + avsys_error(AVAUDIO,"avsys_audio_unlock_sync() failed in %s\n",__func__); + return AVSYS_STATE_ERR_INTERNAL; + } + } + return AVSYS_STATE_SUCCESS; +} + +static bool __avsys_audio_path_check_cp_audio(int gain) +{ + /*If video call uses CP audio, add AVSYS_AUDIO_GAIN_EX_VIDEOCALL to following code. */ + if (gain == AVSYS_AUDIO_GAIN_EX_VOICECALL) + return true; + else + return false; +} + +int avsys_audio_path_set_volume(int handle) +{ + avsys_audio_path_ex_info_t *control = NULL; + avsys_audio_path_ex_info_t **temp = NULL; + avsys_audio_handle_t *ptr = NULL; + int err; + int gain_type; + int out_device = AVSYS_AUDIO_DEVICE_TYPE_SPK; + + err = avsys_audio_handle_get_ptr(handle, &ptr, HANDLE_PTR_MODE_NORMAL); + if (AVSYS_FAIL(err)) { + avsys_error(AVAUDIO, "Handle is not allocated\n"); + avsys_audio_handle_release_ptr(handle, HANDLE_PTR_MODE_NORMAL); + return AVSYS_STATE_ERR_INVALID_PARAMETER; + } + + temp = &control; + avsys_assert(AVSYS_SUCCESS(avsys_audio_get_shm(AVSYS_AUDIO_SHM_IDEN_PATH, (void **)temp))); + avsys_assert(control != NULL); + avsys_assert(AVSYS_SUCCESS(avsys_audio_lock_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))); + + if (__avsys_audio_path_check_cp_audio(control->gain.playback)) + ptr->during_cp_audio = 1; + else + ptr->during_cp_audio = 0; + + gain_type = ptr->gain_setting.vol_type; + out_device = control->lvol_dev_type; + if (control->path_status.playback == PS_PATH_NONE) { + ptr->path_off = 1; + avsys_warning(AVAUDIO, "Path off status...set logical volume device type to speaker\n"); + out_device = AVSYS_AUDIO_LVOL_DEV_TYPE_SPK; + } + avsys_assert(AVSYS_SUCCESS(avsys_audio_unlock_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))); + avsys_warning(AVAUDIO, "set path volume : gain(%d), out_dev(%d)\n", gain_type, out_device); + err = avsys_audio_logical_volume_set_table(gain_type, out_device, &ptr->gain_setting); + avsys_audio_handle_release_ptr(handle, HANDLE_PTR_MODE_NORMAL); + return err; +} + +int avsys_audio_path_set_route_policy(avsys_audio_route_policy_t route) +{ + avsys_audio_path_ex_info_t *control = NULL; + avsys_audio_path_ex_info_t **temp = NULL; + int err = AVSYS_STATE_SUCCESS; + + temp = &control; + avsys_assert(AVSYS_SUCCESS(avsys_audio_get_shm(AVSYS_AUDIO_SHM_IDEN_PATH, (void **)temp))); + avsys_assert(control != NULL); + avsys_assert(AVSYS_SUCCESS(avsys_audio_lock_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))); + + control->route_policy = route; + + avsys_assert(AVSYS_SUCCESS(avsys_audio_unlock_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))); + return err; +} + +int avsys_audio_path_get_route_policy(avsys_audio_route_policy_t *route) +{ + avsys_audio_path_ex_info_t *control = NULL; + avsys_audio_path_ex_info_t **temp = NULL; + int err = AVSYS_STATE_SUCCESS; + + if (!route) + return AVSYS_STATE_ERR_INVALID_PARAMETER; + + temp = &control; + avsys_assert(AVSYS_SUCCESS(avsys_audio_get_shm(AVSYS_AUDIO_SHM_IDEN_PATH, (void **)temp))); + avsys_assert(control != NULL); + avsys_assert(AVSYS_SUCCESS(avsys_audio_lock_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))); + + *route = control->route_policy; + + avsys_assert(AVSYS_SUCCESS(avsys_audio_unlock_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))); + return err; +} + +int avsys_audio_path_check_loud(bool *loud) +{ + avsys_audio_path_ex_info_t *control = NULL; + avsys_audio_path_ex_info_t **temp = NULL; + int err = AVSYS_STATE_SUCCESS; + + if (!loud) + return AVSYS_STATE_ERR_INVALID_PARAMETER; + + temp = &control; + avsys_assert(AVSYS_SUCCESS(avsys_audio_get_shm(AVSYS_AUDIO_SHM_IDEN_PATH, (void **)temp))); + avsys_assert(control != NULL); + avsys_assert(AVSYS_SUCCESS(avsys_audio_lock_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))); + + if ((control->path_status.playback & PS_AP_TO_SPK) || + (control->path_status.playback & PS_AP_TO_RECV) || + (control->path_status.playback & PS_FMRADIO_TO_SPK)) { + *loud = true; + } else { + avsys_info(AVAUDIO, "playback path status 0x%x\n", control->path_status.playback); + *loud = false; + } + + avsys_assert(AVSYS_SUCCESS(avsys_audio_unlock_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))); + return err; +} + +int avsys_audio_path_check_cp_audio(bool *cpaudio, bool *btpath) +{ + avsys_audio_path_ex_info_t *control = NULL; + avsys_audio_path_ex_info_t **temp = NULL; + + if (!cpaudio || !btpath) + return AVSYS_STATE_ERR_INVALID_PARAMETER; + + temp = &control; + avsys_assert(AVSYS_SUCCESS(avsys_audio_get_shm(AVSYS_AUDIO_SHM_IDEN_PATH, (void **)temp))); + avsys_assert(control != NULL); + avsys_assert(AVSYS_SUCCESS(avsys_audio_lock_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))); + + if (__avsys_audio_path_check_cp_audio(control->gain.playback)) + *cpaudio = true; + else + *cpaudio = false; + + if (control->path.playback == AVSYS_AUDIO_PATH_EX_BTHEADSET) + *btpath = true; + else + *btpath = false; + + avsys_assert(AVSYS_SUCCESS(avsys_audio_unlock_sync(AVSYS_AUDIO_SYNC_IDEN_PATH))); + return AVSYS_STATE_SUCCESS; +} + +int avsys_audio_path_set_single_ascn(char *str) +{ + if (!str) + return AVSYS_STATE_ERR_INVALID_PARAMETER; + + RET_IO_CTL_ERR_IF_FAIL(avsys_audio_ascn_single_set(str)) + + return AVSYS_STATE_SUCCESS; +} |