4 * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
29 #include "tizen-audio-internal.h"
30 #include "tizen-audio-impl.h"
32 #include <system_info.h>
33 #define FEATURE_DISPLAY "http://tizen.org/feature/display"
35 /* #define DEBUG_TIMING */
37 static device_type_t outDeviceTypes[] = {
38 { AUDIO_DEVICE_OUT_SPEAKER, "Speaker" },
39 { AUDIO_DEVICE_OUT_BT_SCO, "Bluetooth" },
40 { AUDIO_DEVICE_OUT_AUX, "Line" },
41 { AUDIO_DEVICE_OUT_HDMI, "HDMI" },
45 static device_type_t inDeviceTypes[] = {
46 { AUDIO_DEVICE_IN_BT_SCO, "BT Mic" },
50 static const char* mode_to_verb_str[] = {
51 AUDIO_USE_CASE_VERB_HIFI,
54 static uint32_t __convert_device_string_to_enum(const char* device_str, uint32_t direction)
58 if (!strncmp(device_str, "builtin-speaker", MAX_NAME_LEN)) {
59 device = AUDIO_DEVICE_OUT_SPEAKER;
60 } else if (!strncmp(device_str, "builtin-receiver", MAX_NAME_LEN)) {
61 device = AUDIO_DEVICE_OUT_RECEIVER;
62 } else if ((!strncmp(device_str, "audio-jack", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_OUT)) {
63 device = AUDIO_DEVICE_OUT_JACK;
64 } else if ((!strncmp(device_str, "bt-sco", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_OUT)) {
65 device = AUDIO_DEVICE_OUT_BT_SCO;
66 } else if (!strncmp(device_str, "aux", MAX_NAME_LEN)) {
67 device = AUDIO_DEVICE_OUT_AUX;
68 } else if (!strncmp(device_str, "hdmi", MAX_NAME_LEN)) {
69 device = AUDIO_DEVICE_OUT_HDMI;
70 } else if ((!strncmp(device_str, "builtin-mic", MAX_NAME_LEN))) {
71 device = AUDIO_DEVICE_IN_MAIN_MIC;
72 } else if ((!strncmp(device_str, "audio-jack", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_IN)) {
73 device = AUDIO_DEVICE_IN_JACK;
74 } else if ((!strncmp(device_str, "bt-sco", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_IN)) {
75 device = AUDIO_DEVICE_IN_BT_SCO;
77 device = AUDIO_DEVICE_NONE;
79 AUDIO_LOG_INFO("device type(%s), enum(0x%x)", device_str, device);
83 static audio_return_t __set_devices(audio_hal_t *ah, const char *verb, device_info_t *devices, uint32_t num_of_devices)
85 audio_return_t audio_ret = AUDIO_RET_OK;
86 uint32_t new_device = 0;
87 const char *active_devices[MAX_DEVICES] = {NULL,};
88 int i = 0, j = 0, dev_idx = 0;
90 AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
91 AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER);
92 AUDIO_RETURN_VAL_IF_FAIL(num_of_devices, AUDIO_ERR_PARAMETER);
94 if (num_of_devices > MAX_DEVICES) {
95 num_of_devices = MAX_DEVICES;
96 AUDIO_LOG_ERROR("error: num_of_devices");
97 return AUDIO_ERR_PARAMETER;
100 if (devices[0].direction == AUDIO_DIRECTION_OUT) {
101 ah->device.active_out &= 0x0;
102 if (ah->device.active_in) {
103 /* check the active in devices */
104 for (j = 0; j < inDeviceTypes[j].type; j++) {
105 if (((ah->device.active_in & (~AUDIO_DEVICE_IN)) & inDeviceTypes[j].type))
106 active_devices[dev_idx++] = inDeviceTypes[j].name;
109 } else if (devices[0].direction == AUDIO_DIRECTION_IN) {
110 ah->device.active_in &= 0x0;
111 if (ah->device.active_out) {
112 /* check the active out devices */
113 for (j = 0; j < outDeviceTypes[j].type; j++) {
114 if (ah->device.active_out & outDeviceTypes[j].type)
115 active_devices[dev_idx++] = outDeviceTypes[j].name;
120 for (i = 0; i < num_of_devices; i++) {
121 new_device = __convert_device_string_to_enum(devices[i].type, devices[i].direction);
122 if (new_device & AUDIO_DEVICE_IN) {
123 for (j = 0; j < inDeviceTypes[j].type; j++) {
124 if (new_device == inDeviceTypes[j].type) {
125 active_devices[dev_idx++] = inDeviceTypes[j].name;
126 ah->device.active_in |= new_device;
130 for (j = 0; j < outDeviceTypes[j].type; j++) {
131 if (new_device == outDeviceTypes[j].type) {
132 active_devices[dev_idx++] = outDeviceTypes[j].name;
133 ah->device.active_out |= new_device;
139 if (active_devices[0] == NULL) {
140 AUDIO_LOG_ERROR("Failed to set device: active device is NULL");
141 return AUDIO_ERR_PARAMETER;
144 audio_ret = _ucm_set_devices(ah, verb, active_devices);
146 AUDIO_LOG_ERROR("Failed to set device: error = %d", audio_ret);
151 static audio_return_t __update_route_ap_playback_capture(audio_hal_t *ah, audio_route_info_t *route_info)
153 audio_return_t audio_ret = AUDIO_RET_OK;
154 device_info_t *devices = NULL;
155 const char *verb = mode_to_verb_str[VERB_NORMAL];
157 AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
158 AUDIO_RETURN_VAL_IF_FAIL(route_info, AUDIO_ERR_PARAMETER);
160 devices = route_info->device_infos;
162 /* To Do: Set modifiers */
163 /* int mod_idx = 0; */
164 /* const char *modifiers[MAX_MODIFIERS] = {NULL,}; */
166 AUDIO_LOG_INFO("update_route_ap_playback_capture++ ");
168 audio_ret = __set_devices(ah, verb, devices, route_info->num_of_devices);
170 AUDIO_LOG_ERROR("Failed to set devices: error = 0x%x", audio_ret);
173 ah->device.mode = VERB_NORMAL;
175 /* To Do: Set modifiers */
177 if (!strncmp("voice_recognition", route_info->role, MAX_NAME_LEN)) {
178 modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_VOICESEARCH;
179 } else if ((!strncmp("alarm", route_info->role, MAX_NAME_LEN))||(!strncmp("notifiication", route_info->role, MAX_NAME_LEN))) {
180 if (ah->device.active_out &= AUDIO_DEVICE_OUT_JACK)
181 modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_DUAL_MEDIA;
183 modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_MEDIA;
185 if (ah->device.active_in)
186 modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_CAMCORDING;
188 modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_MEDIA;
190 audio_ret = _audio_ucm_set_modifiers (ah, verb, modifiers);
196 static audio_return_t __update_route_voip(audio_hal_t *ah, device_info_t *devices, int32_t num_of_devices)
198 audio_return_t audio_ret = AUDIO_RET_OK;
199 const char *verb = mode_to_verb_str[VERB_NORMAL];
201 AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
202 AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER);
204 AUDIO_LOG_INFO("update_route_voip++");
206 audio_ret = __set_devices(ah, verb, devices, num_of_devices);
208 AUDIO_LOG_ERROR("Failed to set devices: error = 0x%x", audio_ret);
211 /* FIXME. If necessary, set VERB_VOIP */
212 ah->device.mode = VERB_NORMAL;
214 /* TO DO: Set modifiers */
218 static audio_return_t __update_route_reset(audio_hal_t *ah, uint32_t direction)
220 audio_return_t audio_ret = AUDIO_RET_OK;
221 const char *active_devices[MAX_DEVICES] = {NULL,};
222 int i = 0, dev_idx = 0;
224 /* FIXME: If you need to reset, set verb inactive */
225 /* const char *verb = NULL; */
226 /* verb = AUDIO_USE_CASE_VERB_INACTIVE; */
228 AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
230 AUDIO_LOG_INFO("update_route_reset++, direction(0x%x)", direction);
232 if (direction == AUDIO_DIRECTION_OUT) {
233 ah->device.active_out &= 0x0;
234 if (ah->device.active_in) {
235 /* check the active in devices */
236 for (i = 0; i < inDeviceTypes[i].type; i++) {
237 if (((ah->device.active_in & (~AUDIO_DEVICE_IN)) & inDeviceTypes[i].type)) {
238 active_devices[dev_idx++] = inDeviceTypes[i].name;
239 AUDIO_LOG_INFO("added for in : %s", inDeviceTypes[i].name);
244 ah->device.active_in &= 0x0;
245 if (ah->device.active_out) {
246 /* check the active out devices */
247 for (i = 0; i < outDeviceTypes[i].type; i++) {
248 if (ah->device.active_out & outDeviceTypes[i].type) {
249 active_devices[dev_idx++] = outDeviceTypes[i].name;
250 AUDIO_LOG_INFO("added for out : %s", outDeviceTypes[i].name);
256 if (active_devices[0] == NULL) {
257 AUDIO_LOG_DEBUG("active device is NULL, no need to update.");
261 if ((audio_ret = _ucm_set_devices(ah, mode_to_verb_str[ah->device.mode], active_devices)))
262 AUDIO_LOG_ERROR("failed to _ucm_set_devices(), ret(0x%x)", audio_ret);
267 static void __audio_routing_playback_rpi3(audio_hal_t *ah)
269 bool display_avail = false;
270 int ret = SYSTEM_INFO_ERROR_NONE;
272 ret = system_info_get_platform_bool(FEATURE_DISPLAY, &display_avail);
273 AUDIO_LOG_INFO("system_info_platform [%s]=[%d], ret[%d]", FEATURE_DISPLAY, display_avail, ret);
274 if (ret != SYSTEM_INFO_ERROR_NONE)
275 AUDIO_LOG_ERROR("Failed to get feature...");
277 if (!display_avail) {
278 /* in case of headless (display is not available), force to use earjack(1) only.
279 supported value : (0)auto (1)earjack (2)hdmi */
280 _mixer_control_set_value(ah, "PCM Playback Route", 1);
284 audio_return_t _audio_routing_init(audio_hal_t *ah)
286 audio_return_t audio_ret = AUDIO_RET_OK;
288 AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
290 ah->device.active_in = 0x0;
291 ah->device.active_out = 0x0;
292 ah->device.mode = VERB_NORMAL;
294 if ((audio_ret = _ucm_init(ah)))
295 AUDIO_LOG_ERROR("failed to _ucm_init(), ret(0x%x)", audio_ret);
297 /* additional setting for rpi3 playback route mixer control */
298 __audio_routing_playback_rpi3(ah);
303 audio_return_t _audio_routing_deinit(audio_hal_t *ah)
305 audio_return_t audio_ret = AUDIO_RET_OK;
307 AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
309 if ((audio_ret = _ucm_deinit(ah)))
310 AUDIO_LOG_ERROR("failed to _ucm_deinit(), ret(0x%x)", audio_ret);
315 audio_return_t audio_update_route(void *audio_handle, audio_route_info_t *info)
317 audio_return_t audio_ret = AUDIO_RET_OK;
318 audio_hal_t *ah = (audio_hal_t *)audio_handle;
319 device_info_t *devices = NULL;
321 AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
322 AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER);
323 AUDIO_RETURN_VAL_IF_FAIL(info->role, AUDIO_ERR_PARAMETER);
325 AUDIO_LOG_INFO("role:%s", info->role);
327 devices = info->device_infos;
329 if (!strncmp("voip", info->role, MAX_NAME_LEN)) {
330 if ((audio_ret = __update_route_voip(ah, devices, info->num_of_devices)))
331 AUDIO_LOG_WARN("update voip route return 0x%x", audio_ret);
333 } else if (!strncmp("reset", info->role, MAX_NAME_LEN)) {
334 if ((audio_ret = __update_route_reset(ah, devices->direction)))
335 AUDIO_LOG_WARN("update reset return 0x%x", audio_ret);
338 /* need to prepare for "alarm","notification","emergency","voice-information","voice-recognition","ringtone" */
339 if ((audio_ret = __update_route_ap_playback_capture(ah, info)))
340 AUDIO_LOG_WARN("update playback route return 0x%x", audio_ret);
345 audio_return_t audio_update_route_option(void *audio_handle, audio_route_option_t *option)
347 audio_return_t audio_ret = AUDIO_RET_OK;
348 audio_hal_t *ah = (audio_hal_t *)audio_handle;
350 AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
351 AUDIO_RETURN_VAL_IF_FAIL(option, AUDIO_ERR_PARAMETER);
353 AUDIO_LOG_INFO("role:%s, name:%s, value:%d", option->role, option->name, option->value);