blob: d526703f745778c9a91b0b1bc612b51f77fb98ab [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "audio_hw_primary"
18/*#define LOG_NDEBUG 0*/
19
20#include <errno.h>
21#include <pthread.h>
22#include <stdint.h>
23#include <sys/time.h>
24#include <stdlib.h>
25#include <dlfcn.h>
26#include <math.h>
27
28#include <cutils/log.h>
29#include <cutils/str_parms.h>
30#include <cutils/properties.h>
31
32#include "audio_hw.h"
33
34#define LIB_ACDB_LOADER "/system/lib/libacdbloader.so"
35#define LIB_CSD_CLIENT "/system/lib/libcsd-client.so"
36#define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
37#define MIXER_CARD 0
38
39#define STRING_TO_ENUM(string) { #string, string }
40
41/* Flags used to initialize acdb_settings variable that goes to ACDB library */
42#define DMIC_FLAG 0x00000002
43#define TTY_OFF 0x00000010
44#define TTY_FULL 0x00000020
45#define TTY_VCO 0x00000040
46#define TTY_HCO 0x00000080
47#define TTY_CLEAR 0xFFFFFF0F
48
49struct string_to_enum {
50 const char *name;
51 uint32_t value;
52};
53
54static const struct string_to_enum out_channels_name_to_enum_table[] = {
55 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
56 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
57 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
58};
59
60static const char * const use_case_table[AUDIO_USECASE_MAX] = {
61 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
62 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
63 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
64 [USECASE_AUDIO_RECORD] = "audio-record",
65 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
66 [USECASE_VOICE_CALL] = "voice-call",
67};
68
69static const int pcm_device_table[AUDIO_USECASE_MAX][2] = {
70 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
71 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {14, 14},
72 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
73 [USECASE_AUDIO_RECORD] = {0, 0},
74 [USECASE_AUDIO_RECORD_LOW_LATENCY] = {14, 14},
75 [USECASE_VOICE_CALL] = {12, 12},
76};
77
78/* Array to store sound devices */
79static const char * const device_table[SND_DEVICE_ALL] = {
80 /* Playback sound devices */
81 [SND_DEVICE_OUT_HANDSET] = "handset",
82 [SND_DEVICE_OUT_SPEAKER] = "speaker",
83 [SND_DEVICE_OUT_HEADPHONES] = "headphones",
84 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones",
85 [SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker",
86 [SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones",
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -080087 [SND_DEVICE_OUT_HDMI] = "hdmi",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080088 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
89 [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -080090 [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = "voice-handset-tmus",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080091
92 /* Capture sound devices */
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -080093 [SND_DEVICE_IN_HANDSET_MIC] = "handset-mic",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080094 [SND_DEVICE_IN_SPEAKER_MIC] = "speaker-mic",
95 [SND_DEVICE_IN_HEADSET_MIC] = "headset-mic",
96 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "voice-speaker-mic",
97 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "voice-headset-mic",
98 [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic",
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -080099 [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800100 [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic",
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800101 [SND_DEVICE_IN_VOICE_DMIC_EF] = "voice-dmic-ef",
102 [SND_DEVICE_IN_VOICE_DMIC_BS] = "voice-dmic-bs",
103 [SND_DEVICE_IN_VOICE_DMIC_EF_TMUS] = "voice-dmic-ef-tmus",
104 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF] = "voice-speaker-dmic-ef",
105 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS] = "voice-speaker-dmic-bs",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800106 [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic",
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800107 [SND_DEVICE_IN_VOICE_REC_DMIC_EF] = "voice-rec-dmic-ef",
108 [SND_DEVICE_IN_VOICE_REC_DMIC_BS] = "voice-rec-dmic-bs",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800109};
110
111static const int acdb_device_table[SND_DEVICE_ALL] = {
112 [SND_DEVICE_OUT_HANDSET] = 7,
113 [SND_DEVICE_OUT_SPEAKER] = 14,
114 [SND_DEVICE_OUT_HEADPHONES] = 10,
115 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = 10,
116 [SND_DEVICE_OUT_VOICE_SPEAKER] = 14,
117 [SND_DEVICE_OUT_VOICE_HEADPHONES] = 10,
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800118 [SND_DEVICE_OUT_HDMI] = 18,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800119 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 14,
120 [SND_DEVICE_OUT_BT_SCO] = 22,
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800121 [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = 81,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800122
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800123 [SND_DEVICE_IN_HANDSET_MIC] = 4,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800124 [SND_DEVICE_IN_SPEAKER_MIC] = 4,
125 [SND_DEVICE_IN_HEADSET_MIC] = 8,
126 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = 11,
127 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = 8,
128 [SND_DEVICE_IN_HDMI_MIC] = 4,
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800129 [SND_DEVICE_IN_BT_SCO_MIC] = 21,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800130 [SND_DEVICE_IN_CAMCORDER_MIC] = 61,
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800131 [SND_DEVICE_IN_VOICE_DMIC_EF] = 6,
132 [SND_DEVICE_IN_VOICE_DMIC_BS] = 5,
133 [SND_DEVICE_IN_VOICE_DMIC_EF_TMUS] = 91,
134 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF] = 13,
135 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS] = 12,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800136 [SND_DEVICE_IN_VOICE_REC_MIC] = 62,
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800137 [SND_DEVICE_IN_VOICE_REC_DMIC_EF] = 62,
138 [SND_DEVICE_IN_VOICE_REC_DMIC_BS] = 62,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800139};
140
141/* Array to store back-end paths */
142static const char * const backend_table[SND_DEVICE_ALL] = {
143 [SND_DEVICE_OUT_HANDSET] = "",
144 [SND_DEVICE_OUT_SPEAKER] = "",
145 [SND_DEVICE_OUT_HEADPHONES] = "",
146 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "",
147 [SND_DEVICE_OUT_VOICE_SPEAKER] = "",
148 [SND_DEVICE_OUT_VOICE_HEADPHONES] = "",
149
150 /* Note: Backend name should start with white space */
151 [SND_DEVICE_OUT_HDMI ] = " hdmi",
152 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = " speaker-and-hdmi",
153 [SND_DEVICE_OUT_BT_SCO] = " bt-sco",
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800154 [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = "",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800155
156 [SND_DEVICE_IN_HANDSET_MIC ] = "",
157 [SND_DEVICE_IN_SPEAKER_MIC] = "",
158 [SND_DEVICE_IN_HEADSET_MIC] = "",
159 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "",
160 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "",
161 [SND_DEVICE_IN_HDMI_MIC] = " hdmi",
162 [SND_DEVICE_IN_BT_SCO_MIC ] = " bt-sco",
163 [SND_DEVICE_IN_CAMCORDER_MIC] = "",
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800164 [SND_DEVICE_IN_VOICE_DMIC_EF] = "",
165 [SND_DEVICE_IN_VOICE_DMIC_BS] = "",
166 [SND_DEVICE_IN_VOICE_DMIC_EF_TMUS] = "",
167 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF] = "",
168 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS] = "",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800169 [SND_DEVICE_IN_VOICE_REC_MIC] = "",
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800170 [SND_DEVICE_IN_VOICE_REC_DMIC_EF] = "",
171 [SND_DEVICE_IN_VOICE_REC_DMIC_BS] = "",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800172};
173
174int edid_get_max_channels(void);
175
176static int get_pcm_device_id(struct audio_route *ar,
177 audio_usecase_t usecase,
178 int device_type)
179{
180 ALOGV("%s: enter: usecase(%d)", __func__, usecase);
181 int device_id;
182 if (device_type == PCM_PLAYBACK)
183 device_id = pcm_device_table[usecase][0];
184 else
185 device_id = pcm_device_table[usecase][1];
186 ALOGV("%s: exit: device_id(%d)", __func__, device_id);
187 return device_id;
188}
189
190static int get_acdb_device_id(snd_device_t snd_device)
191{
192 ALOGV("%s: enter: snd_devie(%d)", __func__, snd_device);
193 int acdb_dev_id = acdb_device_table[snd_device];
194 ALOGV("%s: exit: acdb_dev_id(%d)", __func__, acdb_dev_id);
195 return acdb_dev_id;
196}
197
198static int enable_audio_route(struct audio_route *ar,
199 audio_usecase_t usecase,
200 snd_device_t snd_device)
201{
202 ALOGV("%s: enter: usecase(%d) snd_device(%d)",
203 __func__, usecase, snd_device);
204 char mixer_path[50];
205 strcpy(mixer_path, use_case_table[usecase]);
206 strcat(mixer_path, backend_table[snd_device]);
207 audio_route_apply_path(ar, mixer_path);
208 ALOGV("%s: exit", __func__);
209 return 0;
210}
211
212static int disable_audio_route(struct audio_route *ar,
213 audio_usecase_t usecase,
214 snd_device_t snd_device)
215{
216 ALOGV("%s: enter: usecase(%d) snd_device(%d)",
217 __func__, usecase, snd_device);
218 char mixer_path[50];
219 strcpy(mixer_path, use_case_table[usecase]);
220 strcat(mixer_path, backend_table[snd_device]);
221 audio_route_reset_path(ar, mixer_path);
222 ALOGV("%s: exit", __func__);
223 return 0;
224}
225
226static int enable_snd_device(struct audio_device *adev,
227 snd_device_t snd_device)
228{
229 int acdb_dev_id, acdb_dev_type;
230
231 ALOGV("%s: enter: snd_device(%d)", __func__, snd_device);
232 acdb_dev_id = get_acdb_device_id(snd_device);
233 if (acdb_dev_id < 0) {
234 ALOGE("%s: Could not find acdb id for device(%d)",
235 __func__, snd_device);
236 return -EINVAL;
237 }
238 if (snd_device >= SND_DEVICE_OUT_BEGIN &&
239 snd_device < SND_DEVICE_OUT_END) {
240 acdb_dev_type = ACDB_DEV_TYPE_OUT;
241 } else {
242 acdb_dev_type = ACDB_DEV_TYPE_IN;
243 }
244 if (adev->acdb_send_audio_cal) {
245 ALOGV("%s: sending audio calibration for snd_device(%d) acdb_id(%d)",
246 __func__, snd_device, acdb_dev_id);
247 adev->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type);
248 } else {
249 ALOGW("%s: Could find the symbol acdb_send_audio_cal from %s",
250 __func__, LIB_ACDB_LOADER);
251 }
252
253 audio_route_apply_path(adev->audio_route, device_table[snd_device]);
254 ALOGV("%s: exit", __func__);
255 return 0;
256}
257
258static int disable_snd_device(struct audio_route *ar,
259 snd_device_t snd_device)
260{
261 ALOGV("%s: enter: snd_device(%d)", __func__, snd_device);
262 audio_route_reset_path(ar, device_table[snd_device]);
263 ALOGV("%s: exit", __func__);
264 return 0;
265}
266
267static int set_hdmi_channels(struct mixer *mixer,
268 int channel_count)
269{
270 struct mixer_ctl *ctl;
271 const char *channel_cnt_str = NULL;
272 const char *mixer_ctl_name = "HDMI_RX Channels";
273 switch (channel_count) {
274 case 8:
275 channel_cnt_str = "Eight"; break;
276 case 7:
277 channel_cnt_str = "Seven"; break;
278 case 6:
279 channel_cnt_str = "Six"; break;
280 case 5:
281 channel_cnt_str = "Five"; break;
282 case 4:
283 channel_cnt_str = "Four"; break;
284 case 3:
285 channel_cnt_str = "Three"; break;
286 default:
287 channel_cnt_str = "Two"; break;
288 }
289 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
290 if (!ctl) {
291 ALOGE("%s: Could not get ctl for mixer cmd - %s",
292 __func__, mixer_ctl_name);
293 return -EINVAL;
294 }
295 ALOGV("HDMI channel count: %s", channel_cnt_str);
296 mixer_ctl_set_enum_by_string(ctl, channel_cnt_str);
297 return 0;
298}
299
300/* must be called with hw device mutex locked */
301static void read_hdmi_channel_masks(struct stream_out *out)
302{
303 int channels = edid_get_max_channels();
304 ALOGE("%s: enter", __func__);
305
306 switch (channels) {
307 /*
308 * Do not handle stereo output in Multi-channel cases
309 * Stereo case is handled in normal playback path
310 */
311 case 6:
312 ALOGV("%s: HDMI supports 5.1", __func__);
313 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
314 break;
315 case 8:
316 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
317 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
318 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
319 break;
320 default:
321 ALOGE("Unsupported number of channels (%d)", channels);
322 break;
323 }
324
325 ALOGE("%s: exit", __func__);
326}
327
328static snd_device_t get_output_snd_device(struct audio_device *adev)
329{
330 audio_source_t source = adev->input_source;
331 audio_mode_t mode = adev->mode;
332 audio_devices_t devices = adev->out_device;
333 snd_device_t snd_device = SND_DEVICE_INVALID;
334
335 ALOGV("%s: enter: output devices(0x%x)", __func__, devices);
336 if (devices == AUDIO_DEVICE_NONE ||
337 devices & AUDIO_DEVICE_BIT_IN) {
338 ALOGV("%s: Invalid output devices (0x%x)", __func__, devices);
339 goto exit;
340 }
341
342 if (mode == AUDIO_MODE_IN_CALL) {
343 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
344 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
345 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES;
346 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
347 snd_device = SND_DEVICE_OUT_BT_SCO;
348 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
349 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
350 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800351 if (adev->is_tmus)
352 snd_device = SND_DEVICE_OUT_VOICE_HANDSET_TMUS;
353 else
354 snd_device = SND_DEVICE_OUT_HANDSET;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800355 }
356 if (snd_device != SND_DEVICE_INVALID) {
357 goto exit;
358 }
359 }
360
361 if (popcount(devices) == 2) {
362 if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
363 AUDIO_DEVICE_OUT_SPEAKER)) {
364 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
365 } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
366 AUDIO_DEVICE_OUT_SPEAKER)) {
367 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
368 } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL |
369 AUDIO_DEVICE_OUT_SPEAKER)) {
370 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
371 } else {
372 ALOGE("%s: Invalid combo device(0x%x)", __func__, devices);
373 goto exit;
374 }
375 }
376 if (popcount(devices) != 1) {
377 ALOGE("%s: Invalid output devices(0x%x)", __func__, devices);
378 goto exit;
379 }
380
381 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
382 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
383 snd_device = SND_DEVICE_OUT_HEADPHONES;
384 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
385 snd_device = SND_DEVICE_OUT_SPEAKER;
386 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
387 snd_device = SND_DEVICE_OUT_BT_SCO;
388 } else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
389 snd_device = SND_DEVICE_OUT_HDMI ;
390 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
391 snd_device = SND_DEVICE_OUT_HANDSET;
392 } else {
393 ALOGE("%s: Unknown device(s) 0x%x", __func__, devices);
394 }
395exit:
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800396 ALOGV("%s: exit: snd_device(%s)", __func__,
397 (snd_device == SND_DEVICE_INVALID) ?
398 "invalid" : device_table[snd_device]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800399 return snd_device;
400}
401
402static snd_device_t get_input_snd_device(struct audio_device *adev)
403{
404 audio_source_t source = adev->input_source;
405 audio_mode_t mode = adev->mode;
406 audio_devices_t out_device = adev->out_device;
407 audio_devices_t in_device = adev->in_device;
408 snd_device_t snd_device = SND_DEVICE_INVALID;
409
410 ALOGV("%s: enter: out_device(0x%x) in_device(0x%x)",
411 __func__, out_device, in_device);
412 if (mode == AUDIO_MODE_IN_CALL) {
413 if (out_device == AUDIO_DEVICE_NONE) {
414 ALOGE("%s: No output device set for voice call", __func__);
415 goto exit;
416 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800417 if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
418 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800419 if (adev->mic_type_analog || adev->fluence_in_voice_call == false) {
420 snd_device = SND_DEVICE_IN_HANDSET_MIC;
421 } else {
422 if (adev->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
423 if (adev->is_tmus)
424 snd_device = SND_DEVICE_IN_VOICE_DMIC_EF_TMUS;
425 else
426 snd_device = SND_DEVICE_IN_VOICE_DMIC_EF;
427 } else if(adev->dualmic_config == DUALMIC_CONFIG_BROADSIDE)
428 snd_device = SND_DEVICE_IN_VOICE_DMIC_BS;
429 else
430 snd_device = SND_DEVICE_IN_HANDSET_MIC;
431 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800432 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
433 snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
434 } else if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
435 snd_device = SND_DEVICE_IN_BT_SCO_MIC ;
436 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800437 if (adev->fluence_in_voice_call &&
438 adev->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
439 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF;
440 } else if (adev->fluence_in_voice_call &&
441 adev->dualmic_config == DUALMIC_CONFIG_BROADSIDE) {
442 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS;
443 } else {
444 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
445 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800446 }
447 } else if (source == AUDIO_SOURCE_CAMCORDER) {
448 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
449 in_device & AUDIO_DEVICE_IN_BACK_MIC) {
450 snd_device = SND_DEVICE_IN_CAMCORDER_MIC;
451 }
452 } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) {
453 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800454 if (adev->fluence_in_voice_rec &&
455 adev->dualmic_config == DUALMIC_CONFIG_ENDFIRE)
456 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_EF;
457 else if (adev->fluence_in_voice_rec &&
458 adev->dualmic_config == DUALMIC_CONFIG_BROADSIDE)
459 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_BS;
460 else
461 snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800462 }
463 } else if (source == AUDIO_SOURCE_DEFAULT) {
464 goto exit;
465 }
466
467 if (snd_device != SND_DEVICE_INVALID) {
468 goto exit;
469 }
470
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800471 if (in_device != AUDIO_DEVICE_NONE &&
472 in_device != AUDIO_DEVICE_IN_VOICE_CALL &&
473 in_device != AUDIO_DEVICE_IN_COMMUNICATION) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800474 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800475 snd_device = SND_DEVICE_IN_HANDSET_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800476 } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800477 /*
478 * PolicyManager selects BACK_MIC only for camcorder recording.
479 * Ideally this condition shouldn't be met.
480 */
481 if (adev->mic_type_analog)
482 snd_device = SND_DEVICE_IN_HANDSET_MIC;
483 else
484 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800485 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
486 snd_device = SND_DEVICE_IN_HEADSET_MIC;
487 } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
488 snd_device = SND_DEVICE_IN_BT_SCO_MIC ;
489 } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) {
490 snd_device = SND_DEVICE_IN_HDMI_MIC;
491 } else {
492 ALOGE("%s: Unknown input device(s) 0x%x", __func__, in_device);
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800493 ALOGW("%s: Using default handset-mic", __func__);
494 snd_device = SND_DEVICE_IN_HANDSET_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800495 }
496 } else {
497 if (out_device & AUDIO_DEVICE_OUT_EARPIECE) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800498 snd_device = SND_DEVICE_IN_HANDSET_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800499 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
500 snd_device = SND_DEVICE_IN_HEADSET_MIC;
501 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
502 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
503 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800504 snd_device = SND_DEVICE_IN_HANDSET_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800505 } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800506 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800507 } else if (out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
508 snd_device = SND_DEVICE_IN_HDMI_MIC;
509 } else {
510 ALOGE("%s: Unknown output device(s) 0x%x", __func__, out_device);
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800511 ALOGW("%s: Using default handset-mic", __func__);
512 snd_device = SND_DEVICE_IN_HANDSET_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800513 }
514 }
515exit:
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800516 ALOGV("%s: exit: in_snd_device(%s)", __func__,
517 (snd_device == SND_DEVICE_INVALID) ?
518 "invalid" : device_table[snd_device]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800519 return snd_device;
520}
521
522static int select_devices(struct audio_device *adev)
523{
524 snd_device_t out_snd_device = SND_DEVICE_INVALID;
525 snd_device_t in_snd_device = SND_DEVICE_INVALID;
526 struct audio_usecase *usecase;
527 int status = 0;
528 int acdb_rx_id, acdb_tx_id;
529 bool in_call_device_switch = false;
530
531 ALOGV("%s: enter", __func__);
532 out_snd_device = get_output_snd_device(adev);
533 in_snd_device = get_input_snd_device(adev);
534
535 if (out_snd_device == adev->cur_out_snd_device && adev->out_snd_device_active &&
536 in_snd_device == adev->cur_in_snd_device && adev->in_snd_device_active) {
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800537 ALOGV("%s: exit: snd_devices (%d and %d) are already active",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800538 __func__, out_snd_device, in_snd_device);
539 return 0;
540 }
541
542 /*
543 * Limitation: While in call, to do a device switch we need to disable
544 * and enable both RX and TX devices though one of them is same as current
545 * device.
546 */
547 if (adev->mode == AUDIO_MODE_IN_CALL &&
548 adev->csd_client != NULL &&
549 out_snd_device != SND_DEVICE_INVALID &&
550 in_snd_device != SND_DEVICE_INVALID &&
551 adev->cur_out_snd_device != SND_DEVICE_INVALID &&
552 adev->cur_in_snd_device != SND_DEVICE_INVALID) {
553 in_call_device_switch = true;
554 }
555
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800556 if (in_call_device_switch) {
557 /* This must be called before disabling the mixer controls on APQ side */
558 if (adev->csd_disable_device == NULL) {
559 ALOGE("%s: dlsym error for csd_client_disable_device",
560 __func__);
561 } else {
562 status = adev->csd_disable_device();
563 if (status < 0) {
564 ALOGE("%s: csd_client_disable_device, failed, error %d",
565 __func__, status);
566 }
567 }
568 }
569
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800570 if ((out_snd_device != adev->cur_out_snd_device || in_call_device_switch)
571 && adev->out_snd_device_active) {
572 usecase = &adev->usecase_list;
573 while (usecase->next != NULL) {
574 usecase = usecase->next;
575 if (usecase->type == PCM_PLAYBACK || usecase->type == VOICE_CALL) {
576 disable_audio_route(adev->audio_route, usecase->id,
577 adev->cur_out_snd_device);
578 }
579 }
580 audio_route_update_mixer(adev->audio_route);
581 /* Disable current rx device */
582 disable_snd_device(adev->audio_route, adev->cur_out_snd_device);
583 adev->out_snd_device_active = false;
584 }
585
586 if ((in_snd_device != adev->cur_in_snd_device || in_call_device_switch)
587 && adev->in_snd_device_active) {
588 usecase = &adev->usecase_list;
589 while (usecase->next != NULL) {
590 usecase = usecase->next;
591 if (usecase->type == PCM_CAPTURE) {
592 disable_audio_route(adev->audio_route, usecase->id,
593 adev->cur_in_snd_device);
594 }
595 }
596 audio_route_update_mixer(adev->audio_route);
597 /* Disable current tx device */
598 disable_snd_device(adev->audio_route, adev->cur_in_snd_device);
599 adev->in_snd_device_active = false;
600 }
601
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800602 if (out_snd_device != SND_DEVICE_INVALID && !adev->out_snd_device_active) {
603 /* Enable new rx device */
604 status = enable_snd_device(adev, out_snd_device);
605 if (status != 0) {
606 ALOGE("%s: Failed to set mixer ctls for snd_device(%d)",
607 __func__, out_snd_device);
608 return status;
609 }
610 adev->out_snd_device_active = true;
611 adev->cur_out_snd_device = out_snd_device;
612 }
613
614 if (in_snd_device != SND_DEVICE_INVALID && !adev->in_snd_device_active) {
615 /* Enable new tx device */
616 status = enable_snd_device(adev, in_snd_device);
617 if (status != 0) {
618 ALOGE("%s: Failed to set mixer ctls for snd_device(%d)",
619 __func__, out_snd_device);
620 return status;
621 }
622 adev->in_snd_device_active = true;
623 adev->cur_in_snd_device = in_snd_device;
624 }
625 audio_route_update_mixer(adev->audio_route);
626
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800627 usecase = &adev->usecase_list;
628 while (usecase->next != NULL) {
629 usecase = usecase->next;
630 if (usecase->type == PCM_PLAYBACK || usecase->type == VOICE_CALL) {
631 usecase->devices = adev->out_device; /* TODO: fix device logic */
632 status = enable_audio_route(adev->audio_route, usecase->id,
633 adev->cur_out_snd_device);
634 } else {
635 status = enable_audio_route(adev->audio_route, usecase->id,
636 adev->cur_in_snd_device);
637 }
638 }
639 audio_route_update_mixer(adev->audio_route);
640
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800641 if (in_call_device_switch) {
642 if (adev->csd_enable_device == NULL) {
643 ALOGE("%s: dlsym error for csd_client_enable_device",
644 __func__);
645 } else {
646 acdb_rx_id = get_acdb_device_id(out_snd_device);
647 acdb_tx_id = get_acdb_device_id(in_snd_device);
648
649 /* ToDo: To make sure acdb_settings is updated properly based on TTY mode */
650 status = adev->csd_enable_device(acdb_rx_id, acdb_tx_id, adev->acdb_settings);
651 if (status < 0) {
652 ALOGE("%s: csd_client_enable_device, failed, error %d",
653 __func__, status);
654 }
655 }
656 }
657
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800658 ALOGV("%s: exit: status(%d)", __func__, status);
659 return status;
660}
661
662static void add_usecase_to_list(struct audio_device *adev,
663 struct audio_usecase *uc_info)
664{
665 struct audio_usecase *first_entry = adev->usecase_list.next;
666 ALOGV("%s: enter: usecase(%d)", __func__, uc_info->id);
667 /* Insert the new entry on the top of the list */
668 adev->usecase_list.next = uc_info;
669 uc_info->next = first_entry;
670 ALOGV("%s: exit", __func__);
671}
672
673static void remove_usecase_from_list(struct audio_device *adev,
674 audio_usecase_t uc_id)
675{
676 struct audio_usecase *uc_to_remove = NULL;
677 struct audio_usecase *list_head = &adev->usecase_list;
678 ALOGV("%s: enter: usecase(%d)", __func__, uc_id);
679 while (list_head->next != NULL) {
680 if (list_head->next->id == uc_id) {
681 uc_to_remove = list_head->next;
682 list_head->next = list_head->next->next;
683 free(uc_to_remove);
684 break;
685 }
686 list_head = list_head->next;
687 }
688 ALOGV("%s: exit", __func__);
689}
690
691static struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
692 audio_usecase_t uc_id)
693{
694 struct audio_usecase *uc_info = NULL;
695 struct audio_usecase *list_head = &adev->usecase_list;
696 ALOGV("%s: enter: uc_id(%d)", __func__, uc_id);
697 while (list_head->next != NULL) {
698 list_head = list_head->next;
699 if (list_head->id == uc_id) {
700 uc_info = list_head;
701 break;
702 }
703 }
704 ALOGV("%s: exit: uc_info(%p)", __func__, uc_info);
705 return uc_info;
706}
707
708static int get_num_active_usecases(struct audio_device *adev)
709{
710 int num_uc = 0;
711 struct audio_usecase *list_head = &adev->usecase_list;
712 while (list_head->next != NULL) {
713 num_uc++;
714 list_head = list_head->next;
715 }
716 return num_uc;
717}
718
719static audio_devices_t get_active_out_devices(struct audio_device *adev,
720 audio_usecase_t usecase)
721{
722 audio_devices_t devices = 0;
723 struct audio_usecase *list_head = &adev->usecase_list;
724 /* Return the output devices of usecases other than given usecase */
725 while (list_head->next != NULL) {
726 list_head = list_head->next;
727 if (list_head->type == PCM_PLAYBACK && list_head->id != usecase) {
728 devices |= list_head->devices;
729 }
730 }
731 return devices;
732}
733
734static audio_devices_t get_voice_call_out_device(struct audio_device *adev)
735{
736 audio_devices_t devices = 0;
737 struct audio_usecase *list_head = &adev->usecase_list;
738 /* Return the output devices of usecases other than given usecase */
739 while (list_head->next != NULL) {
740 list_head = list_head->next;
741 if (list_head->id == USECASE_VOICE_CALL) {
742 devices = list_head->devices;
743 break;
744 }
745 }
746 return devices;
747}
748
749static int stop_input_stream(struct stream_in *in)
750{
751 int i, ret = 0;
752 snd_device_t in_snd_device;
753 struct audio_usecase *uc_info;
754 struct audio_device *adev = in->dev;
755
756 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
757 adev->input_source = AUDIO_SOURCE_DEFAULT;
758 adev->in_device = AUDIO_DEVICE_NONE;
759
760 uc_info = get_usecase_from_list(adev, in->usecase);
761 if (uc_info == NULL) {
762 ALOGE("%s: Could not find the usecase (%d) in the list",
763 __func__, in->usecase);
764 return -EINVAL;
765 }
766
767 /* 1. Close the PCM device first */
768 if (in->pcm) {
769 pcm_close(in->pcm);
770 in->pcm = NULL;
771 }
772
773 /* 2. Disable stream specific mixer controls */
774 in_snd_device = adev->cur_in_snd_device;
775 disable_audio_route(adev->audio_route, in->usecase, in_snd_device);
776 audio_route_update_mixer(adev->audio_route);
777
778 remove_usecase_from_list(adev, in->usecase);
779
780 /* 3. Disable the tx device */
781 select_devices(adev);
782
783 ALOGV("%s: exit: status(%d)", __func__, ret);
784 return ret;
785}
786
787int start_input_stream(struct stream_in *in)
788{
789 /* 1. Enable output device and stream routing controls */
790 int status, ret = 0;
791 snd_device_t in_snd_device;
792 struct audio_usecase *uc_info;
793 struct audio_device *adev = in->dev;
794
795 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
796 adev->input_source = in->source;
797 adev->in_device = in->device;
798 in_snd_device = get_input_snd_device(adev);
799 if (in_snd_device == SND_DEVICE_INVALID) {
800 ALOGE("%s: Could not get valid input sound device", __func__);
801 /*
802 * TODO: use a single exit point to avoid duplicating code to
803 * reset input source and device
804 */
805 adev->input_source = AUDIO_SOURCE_DEFAULT;
806 adev->in_device = AUDIO_DEVICE_NONE;
807 return -EINVAL;
808 }
809
810 in->pcm_device_id = get_pcm_device_id(adev->audio_route,
811 in->usecase,
812 PCM_CAPTURE);
813 if (in->pcm_device_id < 0) {
814 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
815 __func__, in->usecase);
816 adev->input_source = AUDIO_SOURCE_DEFAULT;
817 adev->in_device = AUDIO_DEVICE_NONE;
818 return -EINVAL;
819 }
820 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
821 uc_info->id = in->usecase;
822 uc_info->type = PCM_CAPTURE;
823 uc_info->devices = in->device;
824
825 /* 1. Enable the TX device */
826 ret = select_devices(adev);
827 if (ret) {
828 ALOGE("%s: Failed to enable device(0x%x)",
829 __func__, adev->in_device);
830 adev->input_source = AUDIO_SOURCE_DEFAULT;
831 adev->in_device = AUDIO_DEVICE_NONE;
832 free(uc_info);
833 return ret;
834 }
835 in_snd_device = adev->cur_in_snd_device;
836
837 /* 2. Enable the mixer controls for the audio route */
838 enable_audio_route(adev->audio_route, in->usecase, in_snd_device);
839 audio_route_update_mixer(adev->audio_route);
840
841 /* 3. Add the usecase info to usecase list */
842 add_usecase_to_list(adev, uc_info);
843
844 /* 2. Open the pcm device */
845 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d)",
846 __func__, SOUND_CARD, in->pcm_device_id);
847 in->pcm = pcm_open(SOUND_CARD, in->pcm_device_id,
848 PCM_IN, &in->config);
849 if (in->pcm && !pcm_is_ready(in->pcm)) {
850 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
851 pcm_close(in->pcm);
852 in->pcm = NULL;
853 status = -EIO;
854 goto error;
855 }
856 ALOGV("%s: exit", __func__);
857 return 0;
858error:
859 ALOGV("%s: exit: status(%d)", __func__, status);
860 stop_input_stream(in);
861 return status;
862}
863
864static int stop_output_stream(struct stream_out *out)
865{
866 int i, ret = 0;
867 snd_device_t out_snd_device;
868 struct audio_usecase *uc_info;
869 struct audio_device *adev = out->dev;
870
871 ALOGV("%s: enter: usecase(%d)", __func__, out->usecase);
872 uc_info = get_usecase_from_list(adev, out->usecase);
873 if (uc_info == NULL) {
874 ALOGE("%s: Could not find the usecase (%d) in the list",
875 __func__, out->usecase);
876 return -EINVAL;
877 }
878
879 /* 1. Close the PCM device first */
880 if (out->pcm) {
881 pcm_close(out->pcm);
882 out->pcm = NULL;
883 }
884
885 /* 2. Get and set stream specific mixer controls */
886 out_snd_device = adev->cur_out_snd_device;
887 disable_audio_route(adev->audio_route, out->usecase, out_snd_device);
888 audio_route_update_mixer(adev->audio_route);
889
890 remove_usecase_from_list(adev, uc_info->id);
891
892 /* 3. Disable the rx device */
893 adev->out_device = get_active_out_devices(adev, out->usecase);
894 adev->out_device |= get_voice_call_out_device(adev);
895 ret = select_devices(adev);
896
897 ALOGV("%s: exit: status(%d)", __func__, ret);
898 return ret;
899}
900
901int start_output_stream(struct stream_out *out)
902{
903 int status;
904 int ret = 0;
905 snd_device_t out_snd_device;
906 struct audio_usecase *uc_info;
907 struct audio_device *adev = out->dev;
908
909 /* 1. Enable output device and stream routing controls */
910 ALOGV("%s: enter: usecase(%d)", __func__, out->usecase);
911 adev->out_device |= out->devices;
912 out_snd_device = get_output_snd_device(adev);
913 if (out_snd_device == SND_DEVICE_INVALID) {
914 ALOGE("%s: Could not get valid output sound device", __func__);
915 /*
916 * TODO: use a single exit point to avoid duplicating code to
917 * reset output device
918 */
919 adev->out_device = get_active_out_devices(adev, out->usecase);
920 adev->out_device |= get_voice_call_out_device(adev);
921 return -EINVAL;
922 }
923
924 out->pcm_device_id = get_pcm_device_id(adev->audio_route,
925 out->usecase,
926 PCM_PLAYBACK);
927 if (out->pcm_device_id < 0) {
928 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
929 __func__, out->pcm_device_id, out->usecase);
930 adev->out_device = get_active_out_devices(adev, out->usecase);
931 adev->out_device |= get_voice_call_out_device(adev);
932 return -EINVAL;
933 }
934
935 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
936 uc_info->id = out->usecase;
937 uc_info->type = PCM_PLAYBACK;
938 uc_info->devices = out->devices;
939
940 ret = select_devices(adev);
941 if (ret) {
942 ALOGE("%s: Failed to enable device(0x%x)",
943 __func__, adev->out_device);
944 adev->out_device = get_active_out_devices(adev, out->usecase);
945 adev->out_device |= get_voice_call_out_device(adev);
946 free(uc_info);
947 return ret;
948 }
949
950 out_snd_device = adev->cur_out_snd_device;
951 enable_audio_route(adev->audio_route, out->usecase, out_snd_device);
952 audio_route_update_mixer(adev->audio_route);
953
954 add_usecase_to_list(adev, uc_info);
955
956 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d)",
957 __func__, 0, out->pcm_device_id);
958 out->pcm = pcm_open(SOUND_CARD, out->pcm_device_id,
959 PCM_OUT, &out->config);
960 if (out->pcm && !pcm_is_ready(out->pcm)) {
961 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
962 pcm_close(out->pcm);
963 out->pcm = NULL;
964 status = -EIO;
965 goto error;
966 }
967 ALOGV("%s: exit", __func__);
968 return 0;
969error:
970 stop_output_stream(out);
971 ALOGE("%s: exit: status(%d)", __func__, status);
972 return status;
973}
974
975static int stop_voice_call(struct audio_device *adev)
976{
977 int i, ret = 0;
978 snd_device_t out_snd_device;
979 struct audio_usecase *uc_info;
980
981 ALOGV("%s: enter: usecase(%d)", __func__, USECASE_VOICE_CALL);
982 if (adev->csd_client) {
983 if (adev->csd_stop_voice == NULL) {
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800984 ALOGE("dlsym error for csd_client_disable_device");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800985 } else {
986 ret = adev->csd_stop_voice();
987 if (ret < 0) {
988 ALOGE("%s: csd_client error %d\n", __func__, ret);
989 }
990 }
991 }
992
993 /* 1. Close the PCM devices */
994 if (adev->voice_call_rx) {
995 pcm_close(adev->voice_call_rx);
996 adev->voice_call_rx = NULL;
997 }
998 if (adev->voice_call_tx) {
999 pcm_close(adev->voice_call_tx);
1000 adev->voice_call_tx = NULL;
1001 }
1002
1003 uc_info = get_usecase_from_list(adev, USECASE_VOICE_CALL);
1004 if (uc_info == NULL) {
1005 ALOGE("%s: Could not find the usecase (%d) in the list",
1006 __func__, USECASE_VOICE_CALL);
1007 return -EINVAL;
1008 }
1009 out_snd_device = adev->cur_out_snd_device;
1010
1011 /* 2. Get and set stream specific mixer controls */
1012 /* ToDo: Status check ?*/
1013 disable_audio_route(adev->audio_route, USECASE_VOICE_CALL, out_snd_device);
1014 audio_route_update_mixer(adev->audio_route);
1015
1016 remove_usecase_from_list(adev, uc_info->id);
1017
1018 /* 3. Disable the rx and tx devices */
1019 ret = select_devices(adev);
1020 adev->in_call = false;
1021
1022 ALOGV("%s: exit: status(%d)", __func__, ret);
1023 return ret;
1024}
1025
1026static int start_voice_call(struct audio_device *adev)
1027{
1028 int i, ret = 0;
1029 snd_device_t out_snd_device;
1030 struct audio_usecase *uc_info;
1031 int pcm_dev_rx_id, pcm_dev_tx_id;
1032
1033 ALOGV("%s: enter", __func__);
1034
1035 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1036 uc_info->id = USECASE_VOICE_CALL;
1037 uc_info->type = VOICE_CALL;
1038 uc_info->devices = adev->out_device;
1039
1040 ret = select_devices(adev);
1041 if (ret) {
1042 free(uc_info);
1043 return ret;
1044 }
1045
1046 /* 2. Get and set stream specific mixer controls */
1047 out_snd_device = adev->cur_out_snd_device;
1048 /* ToDo: Status check ?*/
1049 enable_audio_route(adev->audio_route, uc_info->id, out_snd_device);
1050 audio_route_update_mixer(adev->audio_route);
1051
1052 add_usecase_to_list(adev, uc_info);
1053
1054 pcm_dev_rx_id = get_pcm_device_id(adev->audio_route, uc_info->id,
1055 PCM_PLAYBACK);
1056 pcm_dev_tx_id = get_pcm_device_id(adev->audio_route, uc_info->id,
1057 PCM_CAPTURE);
1058
1059 /* 2. Open the pcm device */
1060 if (pcm_dev_rx_id < 0 || pcm_dev_tx_id < 0) {
1061 ALOGE("%s: Invalid PCM devices (rx: %d tx: %d) for the usecase(%d)",
1062 __func__, pcm_dev_rx_id, pcm_dev_tx_id, uc_info->id);
1063 stop_voice_call(adev);
1064 goto error;
1065 }
1066
1067 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d)",
1068 __func__, SOUND_CARD, pcm_dev_rx_id);
1069 adev->voice_call_rx = pcm_open(SOUND_CARD,
1070 pcm_dev_rx_id,
1071 PCM_OUT, &pcm_config_voice_call);
1072 if (adev->voice_call_rx && !pcm_is_ready(adev->voice_call_rx)) {
1073 ALOGE("%s: %s", __func__, pcm_get_error(adev->voice_call_rx));
1074 /* ToDo: Check return status ??*/
1075 stop_voice_call(adev);
1076 return -EIO;
1077 }
1078
1079 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d)",
1080 __func__, SOUND_CARD, pcm_dev_tx_id);
1081 adev->voice_call_tx = pcm_open(SOUND_CARD,
1082 pcm_dev_tx_id,
1083 PCM_IN, &pcm_config_voice_call);
1084 if (adev->voice_call_tx && !pcm_is_ready(adev->voice_call_tx)) {
1085 ALOGE("%s: %s", __func__, pcm_get_error(adev->voice_call_tx));
1086 /* ToDo: Check return status ??*/
1087 stop_voice_call(adev);
1088 return -EIO;
1089 }
1090 pcm_start(adev->voice_call_rx);
1091 pcm_start(adev->voice_call_tx);
1092
1093 if (adev->csd_client) {
1094 if (adev->csd_start_voice == NULL) {
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001095 ALOGE("dlsym error for csd_client_start_voice");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001096 } else {
1097 ret = adev->csd_start_voice();
1098 if (ret < 0) {
1099 ALOGE("%s: csd_client error %d\n", __func__, ret);
1100 }
1101 }
1102 }
1103
1104 adev->in_call = true;
1105error:
1106 ALOGV("%s: exit: status(%d)", __func__, ret);
1107 return ret;
1108}
1109
1110static int check_input_parameters(uint32_t sample_rate,
1111 audio_format_t format,
1112 int channel_count)
1113{
1114 if (format != AUDIO_FORMAT_PCM_16_BIT) return -EINVAL;
1115
1116 if ((channel_count < 1) || (channel_count > 2)) return -EINVAL;
1117
1118 switch (sample_rate) {
1119 case 8000:
1120 case 11025:
1121 case 12000:
1122 case 16000:
1123 case 22050:
1124 case 24000:
1125 case 32000:
1126 case 44100:
1127 case 48000:
1128 break;
1129 default:
1130 return -EINVAL;
1131 }
1132
1133 return 0;
1134}
1135
1136static size_t get_input_buffer_size(uint32_t sample_rate,
1137 audio_format_t format,
1138 int channel_count)
1139{
1140 size_t size = 0;
1141
1142 if (check_input_parameters(sample_rate, format, channel_count) != 0) return 0;
1143
1144 if (sample_rate == 8000 || sample_rate == 16000 || sample_rate == 32000) {
1145 size = (sample_rate * 20) / 1000;
1146 } else if (sample_rate == 11025 || sample_rate == 12000) {
1147 size = 256;
1148 } else if (sample_rate == 22050 || sample_rate == 24000) {
1149 size = 512;
1150 } else if (sample_rate == 44100 || sample_rate == 48000) {
1151 size = 1024;
1152 }
1153
1154 return size * sizeof(short) * channel_count;
1155}
1156
1157static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1158{
1159 struct stream_out *out = (struct stream_out *)stream;
1160
1161 return out->config.rate;
1162}
1163
1164static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
1165{
1166 return -ENOSYS;
1167}
1168
1169static size_t out_get_buffer_size(const struct audio_stream *stream)
1170{
1171 struct stream_out *out = (struct stream_out *)stream;
1172
1173 return out->config.period_size * audio_stream_frame_size(stream);
1174}
1175
1176static uint32_t out_get_channels(const struct audio_stream *stream)
1177{
1178 struct stream_out *out = (struct stream_out *)stream;
1179
1180 return out->channel_mask;
1181}
1182
1183static audio_format_t out_get_format(const struct audio_stream *stream)
1184{
1185 return AUDIO_FORMAT_PCM_16_BIT;
1186}
1187
1188static int out_set_format(struct audio_stream *stream, audio_format_t format)
1189{
1190 return -ENOSYS;
1191}
1192
1193static int out_standby(struct audio_stream *stream)
1194{
1195 struct stream_out *out = (struct stream_out *)stream;
1196 struct audio_device *adev = out->dev;
1197 ALOGV("%s: enter: usecase(%d)", __func__, out->usecase);
1198 pthread_mutex_lock(&out->dev->lock);
1199 pthread_mutex_lock(&out->lock);
1200
1201 if (!out->standby) {
1202 out->standby = true;
1203 stop_output_stream(out);
1204 }
1205 pthread_mutex_unlock(&out->lock);
1206 pthread_mutex_unlock(&out->dev->lock);
1207 ALOGV("%s: exit", __func__);
1208 return 0;
1209}
1210
1211static int out_dump(const struct audio_stream *stream, int fd)
1212{
1213 return 0;
1214}
1215
1216static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1217{
1218 struct stream_out *out = (struct stream_out *)stream;
1219 struct audio_device *adev = out->dev;
1220 struct str_parms *parms;
1221 char value[32];
1222 int ret, val = 0;
1223
1224 ALOGV("%s: enter: usecase(%d) kvpairs: %s",
1225 __func__, out->usecase, kvpairs);
1226 parms = str_parms_create_str(kvpairs);
1227 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1228 if (ret >= 0) {
1229 val = atoi(value);
1230 pthread_mutex_lock(&adev->lock);
1231 pthread_mutex_lock(&out->lock);
1232
1233 if (adev->mode == AUDIO_MODE_IN_CALL && !adev->in_call) {
1234 adev->out_device = get_active_out_devices(adev, out->usecase) | val;
1235 start_voice_call(adev);
1236 } else if (adev->mode != AUDIO_MODE_IN_CALL && adev->in_call) {
1237 adev->out_device = get_active_out_devices(adev, out->usecase) | val;
1238 stop_voice_call(adev);
1239 } else if ((adev->out_device != (audio_devices_t)val) && (val != 0)) {
1240 if (!out->standby || adev->in_call) {
1241 adev->out_device = get_active_out_devices(adev, out->usecase) | val;
1242 ret = select_devices(adev);
1243 }
1244 }
1245 out->devices = val;
1246
1247 pthread_mutex_unlock(&out->lock);
1248 pthread_mutex_unlock(&adev->lock);
1249 }
1250 str_parms_destroy(parms);
1251 ALOGV("%s: exit: code(%d)", __func__, ret);
1252 return ret;
1253}
1254
1255static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1256{
1257 struct stream_out *out = (struct stream_out *)stream;
1258 struct str_parms *query = str_parms_create_str(keys);
1259 char *str;
1260 char value[256];
1261 struct str_parms *reply = str_parms_create();
1262 size_t i, j;
1263 int ret;
1264 bool first = true;
1265 ALOGV("%s: enter: keys - %s", __func__, keys);
1266 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1267 if (ret >= 0) {
1268 value[0] = '\0';
1269 i = 0;
1270 while (out->supported_channel_masks[i] != 0) {
1271 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1272 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1273 if (!first) {
1274 strcat(value, "|");
1275 }
1276 strcat(value, out_channels_name_to_enum_table[j].name);
1277 first = false;
1278 break;
1279 }
1280 }
1281 i++;
1282 }
1283 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1284 str = str_parms_to_str(reply);
1285 } else {
1286 str = strdup(keys);
1287 }
1288 str_parms_destroy(query);
1289 str_parms_destroy(reply);
1290 ALOGV("%s: exit: returns - %s", __func__, str);
1291 return str;
1292}
1293
1294static uint32_t out_get_latency(const struct audio_stream_out *stream)
1295{
1296 struct stream_out *out = (struct stream_out *)stream;
1297
1298 return (out->config.period_count * out->config.period_size * 1000) / (out->config.rate);
1299}
1300
1301static int out_set_volume(struct audio_stream_out *stream, float left,
1302 float right)
1303{
1304 return -ENOSYS;
1305}
1306
1307static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
1308 size_t bytes)
1309{
1310 struct stream_out *out = (struct stream_out *)stream;
1311 struct audio_device *adev = out->dev;
1312 int i, ret = -1;
1313
1314 /* acquiring hw device mutex systematically is useful if a low priority thread is waiting
1315 * on the output stream mutex - e.g. executing select_mode() while holding the hw device
1316 * mutex
1317 */
1318 pthread_mutex_lock(&adev->lock);
1319 pthread_mutex_lock(&out->lock);
1320 if (out->standby) {
1321 ret = start_output_stream(out);
1322 if (ret != 0) {
1323 pthread_mutex_unlock(&adev->lock);
1324 goto exit;
1325 }
1326 out->standby = false;
1327 }
1328 pthread_mutex_unlock(&adev->lock);
1329
1330 if (out->pcm) {
1331 //ALOGV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
1332 ret = pcm_write(out->pcm, (void *)buffer, bytes);
1333 }
1334
1335exit:
1336 pthread_mutex_unlock(&out->lock);
1337
1338 if (ret != 0) {
1339 out_standby(&out->stream.common);
1340 usleep(bytes * 1000000 / audio_stream_frame_size(&out->stream.common) /
1341 out_get_sample_rate(&out->stream.common));
1342 }
1343 return bytes;
1344}
1345
1346static int out_get_render_position(const struct audio_stream_out *stream,
1347 uint32_t *dsp_frames)
1348{
1349 return -EINVAL;
1350}
1351
1352static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1353{
1354 return 0;
1355}
1356
1357static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1358{
1359 return 0;
1360}
1361
1362static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
1363 int64_t *timestamp)
1364{
1365 return -EINVAL;
1366}
1367
1368/** audio_stream_in implementation **/
1369static uint32_t in_get_sample_rate(const struct audio_stream *stream)
1370{
1371 struct stream_in *in = (struct stream_in *)stream;
1372
1373 return in->config.rate;
1374}
1375
1376static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
1377{
1378 return -ENOSYS;
1379}
1380
1381static size_t in_get_buffer_size(const struct audio_stream *stream)
1382{
1383 struct stream_in *in = (struct stream_in *)stream;
1384
1385 return in->config.period_size * audio_stream_frame_size(stream);
1386}
1387
1388static uint32_t in_get_channels(const struct audio_stream *stream)
1389{
1390 struct stream_in *in = (struct stream_in *)stream;
1391
1392 return in->channel_mask;
1393}
1394
1395static audio_format_t in_get_format(const struct audio_stream *stream)
1396{
1397 return AUDIO_FORMAT_PCM_16_BIT;
1398}
1399
1400static int in_set_format(struct audio_stream *stream, audio_format_t format)
1401{
1402 return -ENOSYS;
1403}
1404
1405static int in_standby(struct audio_stream *stream)
1406{
1407 struct stream_in *in = (struct stream_in *)stream;
1408 struct audio_device *adev = in->dev;
1409 int status = 0;
1410 ALOGV("%s: enter", __func__);
1411 pthread_mutex_lock(&adev->lock);
1412 pthread_mutex_lock(&in->lock);
1413 if (!in->standby) {
1414 adev->input_source = AUDIO_SOURCE_DEFAULT;
1415 adev->in_device = AUDIO_DEVICE_NONE;
1416 in->standby = true;
1417 status = stop_input_stream(in);
1418 }
1419 pthread_mutex_unlock(&in->lock);
1420 pthread_mutex_unlock(&adev->lock);
1421 ALOGV("%s: exit: status(%d)", __func__, status);
1422 return status;
1423}
1424
1425static int in_dump(const struct audio_stream *stream, int fd)
1426{
1427 return 0;
1428}
1429
1430static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
1431{
1432 struct stream_in *in = (struct stream_in *)stream;
1433 struct audio_device *adev = in->dev;
1434 struct str_parms *parms;
1435 char *str;
1436 char value[32];
1437 int ret, val = 0;
1438
1439 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
1440 parms = str_parms_create_str(kvpairs);
1441
1442 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
1443
1444 pthread_mutex_lock(&adev->lock);
1445 pthread_mutex_lock(&in->lock);
1446 if (ret >= 0) {
1447 val = atoi(value);
1448 /* no audio source uses val == 0 */
1449 if ((in->source != val) && (val != 0)) {
1450 in->source = val;
1451 }
1452 }
1453
1454 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1455 if (ret >= 0) {
1456 val = atoi(value);
1457 if ((in->device != val) && (val != 0)) {
1458 in->device = val;
1459 /* If recording is in progress, change the tx device to new device */
1460 if (!in->standby) {
1461 adev->input_source = in->source;
1462 adev->in_device = in->device;
1463 ret = select_devices(adev);
1464 }
1465 }
1466 }
1467
1468 pthread_mutex_unlock(&in->lock);
1469 pthread_mutex_unlock(&adev->lock);
1470
1471 str_parms_destroy(parms);
1472 ALOGV("%s: exit: status(%d)", __func__, ret);
1473 return ret;
1474}
1475
1476static char* in_get_parameters(const struct audio_stream *stream,
1477 const char *keys)
1478{
1479 return strdup("");
1480}
1481
1482static int in_set_gain(struct audio_stream_in *stream, float gain)
1483{
1484 return 0;
1485}
1486
1487static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
1488 size_t bytes)
1489{
1490 struct stream_in *in = (struct stream_in *)stream;
1491 struct audio_device *adev = in->dev;
1492 int i, ret = -1;
1493
1494 /* acquiring hw device mutex systematically is useful if a low priority thread is waiting
1495 * on the output stream mutex - e.g. executing select_mode() while holding the hw device
1496 * mutex
1497 */
1498 //ALOGV("%s: buffer(%p) bytes(%d)", __func__, buffer, bytes);
1499 pthread_mutex_lock(&adev->lock);
1500 pthread_mutex_lock(&in->lock);
1501 if (in->standby) {
1502 ret = start_input_stream(in);
1503 if (ret != 0) {
1504 pthread_mutex_unlock(&adev->lock);
1505 goto exit;
1506 }
1507 in->standby = 0;
1508 }
1509 pthread_mutex_unlock(&adev->lock);
1510
1511 if (in->pcm) {
1512 ret = pcm_read(in->pcm, buffer, bytes);
1513 }
1514
1515 /*
1516 * Instead of writing zeroes here, we could trust the hardware
1517 * to always provide zeroes when muted.
1518 */
1519 if (ret == 0 && adev->mic_mute)
1520 memset(buffer, 0, bytes);
1521
1522exit:
1523 pthread_mutex_unlock(&in->lock);
1524
1525 if (ret != 0) {
1526 in_standby(&in->stream.common);
1527 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
1528 usleep(bytes * 1000000 / audio_stream_frame_size(&in->stream.common) /
1529 in_get_sample_rate(&in->stream.common));
1530 }
1531 return bytes;
1532}
1533
1534static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
1535{
1536 return 0;
1537}
1538
1539static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1540{
1541 return 0;
1542}
1543
1544static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1545{
1546 return 0;
1547}
1548
1549static int adev_open_output_stream(struct audio_hw_device *dev,
1550 audio_io_handle_t handle,
1551 audio_devices_t devices,
1552 audio_output_flags_t flags,
1553 struct audio_config *config,
1554 struct audio_stream_out **stream_out)
1555{
1556 struct audio_device *adev = (struct audio_device *)dev;
1557 struct stream_out *out;
1558 int i, ret;
1559
1560 ALOGV("%s: enter: sample_rate(%d) channel_mask(0x%x) devices(0x%x) flags(0x%x)",
1561 __func__, config->sample_rate, config->channel_mask, devices, flags);
1562 *stream_out = NULL;
1563 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
1564
1565 if (devices == AUDIO_DEVICE_NONE)
1566 devices = AUDIO_DEVICE_OUT_SPEAKER;
1567
1568 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
1569 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
1570 out->flags = flags;
1571 out->devices = devices;
1572
1573 /* Init use case and pcm_config */
1574 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
1575 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1576 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
1577 out->config = pcm_config_hdmi_multi;
1578
1579 pthread_mutex_lock(&adev->lock);
1580 read_hdmi_channel_masks(out);
1581 pthread_mutex_unlock(&adev->lock);
1582
1583 if (config->sample_rate == 0) config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1584 if (config->channel_mask == 0) config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
1585 out->channel_mask = config->channel_mask;
1586 out->config.rate = config->sample_rate;
1587 out->config.channels = popcount(out->channel_mask);
1588 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
1589 set_hdmi_channels(adev->mixer, out->config.channels);
1590 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
1591 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
1592 out->config = pcm_config_deep_buffer;
1593 } else {
1594 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
1595 out->config = pcm_config_low_latency;
1596 }
1597
1598 /* Check if this usecase is already existing */
1599 pthread_mutex_lock(&adev->lock);
1600 if (get_usecase_from_list(adev, out->usecase) != NULL) {
1601 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
1602 free(out);
1603 *stream_out = NULL;
1604 pthread_mutex_unlock(&adev->lock);
1605 return -EEXIST;
1606 }
1607 pthread_mutex_unlock(&adev->lock);
1608
1609 out->stream.common.get_sample_rate = out_get_sample_rate;
1610 out->stream.common.set_sample_rate = out_set_sample_rate;
1611 out->stream.common.get_buffer_size = out_get_buffer_size;
1612 out->stream.common.get_channels = out_get_channels;
1613 out->stream.common.get_format = out_get_format;
1614 out->stream.common.set_format = out_set_format;
1615 out->stream.common.standby = out_standby;
1616 out->stream.common.dump = out_dump;
1617 out->stream.common.set_parameters = out_set_parameters;
1618 out->stream.common.get_parameters = out_get_parameters;
1619 out->stream.common.add_audio_effect = out_add_audio_effect;
1620 out->stream.common.remove_audio_effect = out_remove_audio_effect;
1621 out->stream.get_latency = out_get_latency;
1622 out->stream.set_volume = out_set_volume;
1623 out->stream.write = out_write;
1624 out->stream.get_render_position = out_get_render_position;
1625 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
1626
1627 out->dev = adev;
1628 out->standby = 1;
1629
1630 config->format = out->stream.common.get_format(&out->stream.common);
1631 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
1632 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
1633
1634 *stream_out = &out->stream;
1635 ALOGV("%s: exit", __func__);
1636 return 0;
1637}
1638
1639static void adev_close_output_stream(struct audio_hw_device *dev,
1640 struct audio_stream_out *stream)
1641{
1642 ALOGV("%s: enter", __func__);
1643 out_standby(&stream->common);
1644 free(stream);
1645 ALOGV("%s: exit", __func__);
1646}
1647
1648static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
1649{
1650 struct audio_device *adev = (struct audio_device *)dev;
1651 struct str_parms *parms;
1652 char *str;
1653 char value[32];
1654 int ret;
1655
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -08001656 ALOGV("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001657
1658 parms = str_parms_create_str(kvpairs);
1659 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_TTY_MODE, value, sizeof(value));
1660 if (ret >= 0) {
1661 int tty_mode;
1662
1663 if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_OFF) == 0)
1664 tty_mode = TTY_MODE_OFF;
1665 else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_VCO) == 0)
1666 tty_mode = TTY_MODE_VCO;
1667 else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_HCO) == 0)
1668 tty_mode = TTY_MODE_HCO;
1669 else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_FULL) == 0)
1670 tty_mode = TTY_MODE_FULL;
1671 else
1672 return -EINVAL;
1673
1674 pthread_mutex_lock(&adev->lock);
1675 if (tty_mode != adev->tty_mode) {
1676 adev->tty_mode = tty_mode;
1677 /* ToDo: Device switch */
1678 }
1679 pthread_mutex_unlock(&adev->lock);
1680 }
1681
1682 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
1683 if (ret >= 0) {
1684 /* When set to false, HAL should disable EC and NS
1685 * But it is currently not supported.
1686 */
1687 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
1688 adev->bluetooth_nrec = true;
1689 else
1690 adev->bluetooth_nrec = false;
1691 }
1692
1693 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
1694 if (ret >= 0) {
1695 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
1696 adev->screen_off = false;
1697 else
1698 adev->screen_off = true;
1699 }
1700
1701 str_parms_destroy(parms);
1702 ALOGV("%s: exit with code(%d)", __func__, ret);
1703 return ret;
1704}
1705
1706static char* adev_get_parameters(const struct audio_hw_device *dev,
1707 const char *keys)
1708{
1709 /* ToDo: Return requested params */
1710 return strdup("");
1711}
1712
1713static int adev_init_check(const struct audio_hw_device *dev)
1714{
1715 return 0;
1716}
1717
1718static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
1719{
1720 struct audio_device *adev = (struct audio_device *)dev;
1721 int vol, err = 0;
1722
1723 pthread_mutex_lock(&adev->lock);
1724 adev->voice_volume = volume;
1725 if (adev->mode == AUDIO_MODE_IN_CALL) {
1726 if (volume < 0.0) {
1727 volume = 0.0;
1728 } else if (volume > 1.0) {
1729 volume = 1.0;
1730 }
1731
1732 vol = lrint(volume * 100.0);
1733
1734 // Voice volume levels from android are mapped to driver volume levels as follows.
1735 // 0 -> 5, 20 -> 4, 40 ->3, 60 -> 2, 80 -> 1, 100 -> 0
1736 // So adjust the volume to get the correct volume index in driver
1737 vol = 100 - vol;
1738
1739 if (adev->csd_client) {
1740 if (adev->csd_volume == NULL) {
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001741 ALOGE("%s: dlsym error for csd_client_volume", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001742 } else {
1743 err = adev->csd_volume(vol);
1744 if (err < 0) {
1745 ALOGE("%s: csd_client error %d", __func__, err);
1746 }
1747 }
1748 } else {
1749 ALOGE("%s: No CSD Client present", __func__);
1750 }
1751 }
1752 pthread_mutex_unlock(&adev->lock);
1753 return err;
1754}
1755
1756static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
1757{
1758 return -ENOSYS;
1759}
1760
1761static int adev_get_master_volume(struct audio_hw_device *dev,
1762 float *volume)
1763{
1764 return -ENOSYS;
1765}
1766
1767static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
1768{
1769 return -ENOSYS;
1770}
1771
1772static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
1773{
1774 return -ENOSYS;
1775}
1776
1777static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
1778{
1779 struct audio_device *adev = (struct audio_device *)dev;
1780
1781 pthread_mutex_lock(&adev->lock);
1782 if (adev->mode != mode) {
1783 adev->mode = mode;
1784 }
1785 pthread_mutex_unlock(&adev->lock);
1786 return 0;
1787}
1788
1789static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
1790{
1791 struct audio_device *adev = (struct audio_device *)dev;
1792 int err = 0;
1793
1794 adev->mic_mute = state;
1795 if (adev->mode == AUDIO_MODE_IN_CALL) {
1796 if (adev->csd_client) {
1797 if (adev->csd_mic_mute == NULL) {
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001798 ALOGE("%s: dlsym error for csd_mic_mute", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001799 } else {
1800 err = adev->csd_mic_mute(state);
1801 if (err < 0) {
1802 ALOGE("%s: csd_client error %d", __func__, err);
1803 }
1804 }
1805 } else {
1806 ALOGE("%s: No CSD Client present", __func__);
1807 }
1808 }
1809 return err;
1810}
1811
1812static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
1813{
1814 struct audio_device *adev = (struct audio_device *)dev;
1815
1816 *state = adev->mic_mute;
1817
1818 return 0;
1819}
1820
1821static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
1822 const struct audio_config *config)
1823{
1824 size_t size;
1825 int channel_count = popcount(config->channel_mask);
1826
1827 return get_input_buffer_size(config->sample_rate, config->format, channel_count);
1828}
1829
1830static int adev_open_input_stream(struct audio_hw_device *dev,
1831 audio_io_handle_t handle,
1832 audio_devices_t devices,
1833 struct audio_config *config,
1834 struct audio_stream_in **stream_in)
1835{
1836 struct audio_device *adev = (struct audio_device *)dev;
1837 struct stream_in *in;
1838 int ret, buffer_size, frame_size;
1839 int channel_count = popcount(config->channel_mask);
1840
1841 ALOGV("%s: enter", __func__);
1842 *stream_in = NULL;
1843 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
1844 return -EINVAL;
1845
1846 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
1847
1848 in->stream.common.get_sample_rate = in_get_sample_rate;
1849 in->stream.common.set_sample_rate = in_set_sample_rate;
1850 in->stream.common.get_buffer_size = in_get_buffer_size;
1851 in->stream.common.get_channels = in_get_channels;
1852 in->stream.common.get_format = in_get_format;
1853 in->stream.common.set_format = in_set_format;
1854 in->stream.common.standby = in_standby;
1855 in->stream.common.dump = in_dump;
1856 in->stream.common.set_parameters = in_set_parameters;
1857 in->stream.common.get_parameters = in_get_parameters;
1858 in->stream.common.add_audio_effect = in_add_audio_effect;
1859 in->stream.common.remove_audio_effect = in_remove_audio_effect;
1860 in->stream.set_gain = in_set_gain;
1861 in->stream.read = in_read;
1862 in->stream.get_input_frames_lost = in_get_input_frames_lost;
1863
1864 in->device = devices;
1865 in->source = AUDIO_SOURCE_DEFAULT;
1866 in->dev = adev;
1867 adev->in_device = devices;
1868 in->standby = 1;
1869 in->channel_mask = config->channel_mask;
1870
1871 /* Update config params with the requested sample rate and channels */
1872 in->usecase = USECASE_AUDIO_RECORD;
1873 in->config = pcm_config_audio_capture;
1874 in->config.channels = channel_count;
1875 in->config.rate = config->sample_rate;
1876
1877 frame_size = audio_stream_frame_size((struct audio_stream *)in);
1878 buffer_size = get_input_buffer_size(config->sample_rate,
1879 config->format,
1880 channel_count);
1881 in->config.period_size = buffer_size / frame_size;
1882
1883 *stream_in = &in->stream;
1884 ALOGV("%s: exit", __func__);
1885 return 0;
1886
1887err_open:
1888 free(in);
1889 *stream_in = NULL;
1890 return ret;
1891}
1892
1893static void adev_close_input_stream(struct audio_hw_device *dev,
1894 struct audio_stream_in *stream)
1895{
1896 in_standby(&stream->common);
1897 free(stream);
1898
1899 return;
1900}
1901
1902static int adev_dump(const audio_hw_device_t *device, int fd)
1903{
1904 return 0;
1905}
1906
1907static int adev_close(hw_device_t *device)
1908{
1909 struct audio_device *adev = (struct audio_device *)device;
1910 audio_route_free(adev->audio_route);
1911 free(device);
1912 return 0;
1913}
1914
1915static void init_platform_data(struct audio_device *adev)
1916{
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -08001917 char platform[PROPERTY_VALUE_MAX];
1918 char baseband[PROPERTY_VALUE_MAX];
1919 char value[PROPERTY_VALUE_MAX];
1920 int mccmnc;
1921
1922 adev->dualmic_config = DUALMIC_CONFIG_NONE;
1923 adev->fluence_in_voice_call = false;
1924 adev->fluence_in_voice_rec = false;
1925 adev->mic_type_analog = false;
1926
1927 property_get("persist.audio.handset.mic.type",value,"");
1928 if (!strncmp("analog", value, 6))
1929 adev->mic_type_analog = true;
1930
1931 property_get("persist.audio.dualmic.config",value,"");
1932 if (!strncmp("broadside", value, 9)) {
1933 adev->dualmic_config = DUALMIC_CONFIG_BROADSIDE;
1934 adev->acdb_settings |= DMIC_FLAG;
1935 } else if (!strncmp("endfire", value, 7)) {
1936 adev->dualmic_config = DUALMIC_CONFIG_ENDFIRE;
1937 adev->acdb_settings |= DMIC_FLAG;
1938 }
1939
1940 if (adev->dualmic_config != DUALMIC_CONFIG_NONE) {
1941 property_get("persist.audio.fluence.voicecall",value,"");
1942 if (!strncmp("true", value, 4)) {
1943 adev->fluence_in_voice_call = true;
1944 }
1945
1946 property_get("persist.audio.fluence.voicerec",value,"");
1947 if (!strncmp("true", value, 4)) {
1948 adev->fluence_in_voice_rec = true;
1949 }
1950 }
1951
1952 property_get("gsm.sim.operator.numeric",value,"0");
1953 mccmnc = atoi(value);
1954 ALOGV("%s: tmus mccmnc %d", __func__, mccmnc);
1955 switch(mccmnc) {
1956 /* TMUS MCC(310), MNC(490, 260, 026) */
1957 case 310490:
1958 case 310260:
1959 case 310026:
1960 adev->is_tmus = true;
1961 break;
1962 default:
1963 adev->is_tmus = false;
1964 break;
1965 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001966
1967 adev->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
1968 if (adev->acdb_handle == NULL) {
1969 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_ACDB_LOADER);
1970 } else {
1971 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_ACDB_LOADER);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001972 adev->acdb_deallocate = (acdb_deallocate_t)dlsym(adev->acdb_handle,
1973 "acdb_loader_deallocate_ACDB");
1974 adev->acdb_send_audio_cal = (acdb_send_audio_cal_t)dlsym(adev->acdb_handle,
1975 "acdb_loader_send_audio_cal");
1976 adev->acdb_send_voice_cal = (acdb_send_voice_cal_t)dlsym(adev->acdb_handle,
1977 "acdb_loader_send_voice_cal");
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001978 adev->acdb_init = (acdb_init_t)dlsym(adev->acdb_handle,
1979 "acdb_loader_init_ACDB");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001980 if (adev->acdb_init == NULL)
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001981 ALOGE("%s: dlsym error %s for acdb_loader_init_ACDB", __func__, dlerror());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001982 else
1983 adev->acdb_init();
1984 }
1985
1986 /* If platform is Fusion3, load CSD Client specific symbols
1987 * Voice call is handled by MDM and apps processor talks to
1988 * MDM through CSD Client
1989 */
1990 property_get("ro.board.platform", platform, "");
1991 property_get("ro.baseband", baseband, "");
1992 if (!strcmp("msm8960", platform) && !strcmp("mdm", baseband)) {
1993 adev->csd_client = dlopen(LIB_CSD_CLIENT, RTLD_NOW);
1994 if (adev->csd_client == NULL)
1995 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_CSD_CLIENT);
1996 }
1997
1998 if (adev->csd_client) {
1999 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_CSD_CLIENT);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002000 adev->csd_client_deinit = (csd_client_deinit_t)dlsym(adev->csd_client,
2001 "csd_client_deinit");
2002 adev->csd_disable_device = (csd_disable_device_t)dlsym(adev->csd_client,
2003 "csd_client_disable_device");
2004 adev->csd_enable_device = (csd_enable_device_t)dlsym(adev->csd_client,
2005 "csd_client_enable_device");
2006 adev->csd_start_voice = (csd_start_voice_t)dlsym(adev->csd_client,
2007 "csd_client_start_voice");
2008 adev->csd_stop_voice = (csd_stop_voice_t)dlsym(adev->csd_client,
2009 "csd_client_stop_voice");
2010 adev->csd_volume = (csd_volume_t)dlsym(adev->csd_client,
2011 "csd_client_volume");
2012 adev->csd_mic_mute = (csd_mic_mute_t)dlsym(adev->csd_client,
2013 "csd_client_mic_mute");
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002014 adev->csd_client_init = (csd_client_init_t)dlsym(adev->csd_client,
2015 "csd_client_init");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002016
2017 if (adev->csd_client_init == NULL) {
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002018 ALOGE("%s: dlsym error %s for csd_client_init", __func__, dlerror());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002019 } else {
2020 adev->csd_client_init();
2021 }
2022 }
2023}
2024
2025static int adev_open(const hw_module_t *module, const char *name,
2026 hw_device_t **device)
2027{
2028 struct audio_device *adev;
2029 int ret;
2030
2031 ALOGV("%s: enter", __func__);
2032 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
2033
2034 adev = calloc(1, sizeof(struct audio_device));
2035
2036 adev->mixer = mixer_open(MIXER_CARD);
2037 if (!adev->mixer) {
2038 ALOGE("Unable to open the mixer, aborting.");
2039 return -ENOSYS;
2040 }
2041
2042 adev->audio_route = audio_route_init(MIXER_CARD, MIXER_XML_PATH);
2043 if (!adev->audio_route) {
2044 free(adev);
2045 ALOGE("%s: Failed to init audio route controls, aborting.", __func__);
2046 *device = NULL;
2047 return -EINVAL;
2048 }
2049
2050 adev->device.common.tag = HARDWARE_DEVICE_TAG;
2051 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
2052 adev->device.common.module = (struct hw_module_t *)module;
2053 adev->device.common.close = adev_close;
2054
2055 adev->device.init_check = adev_init_check;
2056 adev->device.set_voice_volume = adev_set_voice_volume;
2057 adev->device.set_master_volume = adev_set_master_volume;
2058 adev->device.get_master_volume = adev_get_master_volume;
2059 adev->device.set_master_mute = adev_set_master_mute;
2060 adev->device.get_master_mute = adev_get_master_mute;
2061 adev->device.set_mode = adev_set_mode;
2062 adev->device.set_mic_mute = adev_set_mic_mute;
2063 adev->device.get_mic_mute = adev_get_mic_mute;
2064 adev->device.set_parameters = adev_set_parameters;
2065 adev->device.get_parameters = adev_get_parameters;
2066 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
2067 adev->device.open_output_stream = adev_open_output_stream;
2068 adev->device.close_output_stream = adev_close_output_stream;
2069 adev->device.open_input_stream = adev_open_input_stream;
2070 adev->device.close_input_stream = adev_close_input_stream;
2071 adev->device.dump = adev_dump;
2072
2073 /* Set the default route before the PCM stream is opened */
2074 pthread_mutex_lock(&adev->lock);
2075 adev->mode = AUDIO_MODE_NORMAL;
2076 adev->input_source = AUDIO_SOURCE_DEFAULT;
2077 adev->out_device = AUDIO_DEVICE_NONE;
2078 adev->in_device = AUDIO_DEVICE_NONE;
2079 adev->voice_call_rx = NULL;
2080 adev->voice_call_tx = NULL;
2081 adev->voice_volume = 1.0f;
2082 adev->tty_mode = TTY_MODE_OFF;
2083 adev->bluetooth_nrec = true;
2084 adev->cur_out_snd_device = 0;
2085 adev->cur_in_snd_device = 0;
2086 adev->out_snd_device_active = false;
2087 adev->in_snd_device_active = false;
2088 adev->usecase_list.next = NULL;
2089 adev->usecase_list.id = USECASE_INVALID;
2090 adev->in_call = false;
2091 adev->acdb_settings = TTY_OFF;
2092 pthread_mutex_unlock(&adev->lock);
2093
2094 /* Loads platform specific libraries dynamically */
2095 init_platform_data(adev);
2096
2097 *device = &adev->device.common;
2098
2099 ALOGV("%s: exit", __func__);
2100 return 0;
2101}
2102
2103static struct hw_module_methods_t hal_module_methods = {
2104 .open = adev_open,
2105};
2106
2107struct audio_module HAL_MODULE_INFO_SYM = {
2108 .common = {
2109 .tag = HARDWARE_MODULE_TAG,
2110 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
2111 .hal_api_version = HARDWARE_HAL_API_VERSION,
2112 .id = AUDIO_HARDWARE_MODULE_ID,
2113 .name = "QCOM Audio HAL",
2114 .author = "Code Aurora Forum",
2115 .methods = &hal_module_methods,
2116 },
2117};