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