blob: 36714bf6e5f86c2c878b31961b788c4f3c7b8f70 [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
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080043#define TTY_MODE_OFF 0x00000010
44#define TTY_MODE_FULL 0x00000020
45#define TTY_MODE_VCO 0x00000040
46#define TTY_MODE_HCO 0x00000080
47#define TTY_MODE_CLEAR 0xFFFFFF0F
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080048
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 Alamandaf9967042013-02-14 19:35:14 -080091 [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = "voice-tty-full-headphones",
92 [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = "voice-tty-vco-headphones",
93 [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = "voice-tty-hco-handset",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080094
95 /* Capture sound devices */
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -080096 [SND_DEVICE_IN_HANDSET_MIC] = "handset-mic",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080097 [SND_DEVICE_IN_SPEAKER_MIC] = "speaker-mic",
98 [SND_DEVICE_IN_HEADSET_MIC] = "headset-mic",
99 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "voice-speaker-mic",
100 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "voice-headset-mic",
101 [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic",
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800102 [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800103 [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic",
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800104 [SND_DEVICE_IN_VOICE_DMIC_EF] = "voice-dmic-ef",
105 [SND_DEVICE_IN_VOICE_DMIC_BS] = "voice-dmic-bs",
106 [SND_DEVICE_IN_VOICE_DMIC_EF_TMUS] = "voice-dmic-ef-tmus",
107 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF] = "voice-speaker-dmic-ef",
108 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS] = "voice-speaker-dmic-bs",
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800109 [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = "voice-tty-full-headset-mic",
110 [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = "voice-tty-vco-handset-mic",
111 [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = "voice-tty-hco-headset-mic",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800112 [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic",
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800113 [SND_DEVICE_IN_VOICE_REC_DMIC_EF] = "voice-rec-dmic-ef",
114 [SND_DEVICE_IN_VOICE_REC_DMIC_BS] = "voice-rec-dmic-bs",
Eric Laurentc8400632013-02-14 19:04:54 -0800115 [SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE] = "voice-rec-dmic-ef-fluence",
116 [SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE] = "voice-rec-dmic-bs-fluence",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800117};
118
Eric Laurentc8400632013-02-14 19:04:54 -0800119/* ACDB IDs (audio DSP path configuration IDs) for each sound device */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800120static const int acdb_device_table[SND_DEVICE_ALL] = {
121 [SND_DEVICE_OUT_HANDSET] = 7,
122 [SND_DEVICE_OUT_SPEAKER] = 14,
123 [SND_DEVICE_OUT_HEADPHONES] = 10,
124 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = 10,
125 [SND_DEVICE_OUT_VOICE_SPEAKER] = 14,
126 [SND_DEVICE_OUT_VOICE_HEADPHONES] = 10,
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800127 [SND_DEVICE_OUT_HDMI] = 18,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800128 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 14,
129 [SND_DEVICE_OUT_BT_SCO] = 22,
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800130 [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = 81,
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800131 [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = 17,
132 [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = 17,
133 [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = 37,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800134
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800135 [SND_DEVICE_IN_HANDSET_MIC] = 4,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800136 [SND_DEVICE_IN_SPEAKER_MIC] = 4,
137 [SND_DEVICE_IN_HEADSET_MIC] = 8,
138 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = 11,
139 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = 8,
140 [SND_DEVICE_IN_HDMI_MIC] = 4,
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800141 [SND_DEVICE_IN_BT_SCO_MIC] = 21,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800142 [SND_DEVICE_IN_CAMCORDER_MIC] = 61,
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800143 [SND_DEVICE_IN_VOICE_DMIC_EF] = 6,
144 [SND_DEVICE_IN_VOICE_DMIC_BS] = 5,
145 [SND_DEVICE_IN_VOICE_DMIC_EF_TMUS] = 91,
146 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF] = 13,
147 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS] = 12,
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800148 [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = 16,
149 [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = 36,
150 [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = 16,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800151 [SND_DEVICE_IN_VOICE_REC_MIC] = 62,
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800152 [SND_DEVICE_IN_VOICE_REC_DMIC_EF] = 62,
153 [SND_DEVICE_IN_VOICE_REC_DMIC_BS] = 62,
Eric Laurentc8400632013-02-14 19:04:54 -0800154 [SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE] = 62,
155 [SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE] = 62,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800156};
157
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800158int edid_get_max_channels(void);
159
160static int get_pcm_device_id(struct audio_route *ar,
161 audio_usecase_t usecase,
162 int device_type)
163{
164 ALOGV("%s: enter: usecase(%d)", __func__, usecase);
165 int device_id;
166 if (device_type == PCM_PLAYBACK)
167 device_id = pcm_device_table[usecase][0];
168 else
169 device_id = pcm_device_table[usecase][1];
170 ALOGV("%s: exit: device_id(%d)", __func__, device_id);
171 return device_id;
172}
173
174static int get_acdb_device_id(snd_device_t snd_device)
175{
176 ALOGV("%s: enter: snd_devie(%d)", __func__, snd_device);
177 int acdb_dev_id = acdb_device_table[snd_device];
178 ALOGV("%s: exit: acdb_dev_id(%d)", __func__, acdb_dev_id);
179 return acdb_dev_id;
180}
181
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800182static void add_backend_name(char *mixer_path,
183 snd_device_t snd_device)
184{
185 if (snd_device == SND_DEVICE_OUT_HDMI ||
186 snd_device == SND_DEVICE_IN_HDMI_MIC)
187 strcat(mixer_path, " hdmi");
188 else if(snd_device == SND_DEVICE_OUT_BT_SCO ||
189 snd_device == SND_DEVICE_IN_BT_SCO_MIC)
190 strcat(mixer_path, " bt-sco");
191 else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HDMI)
192 strcat(mixer_path, " speaker-and-hdmi");
193}
194
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800195static int enable_audio_route(struct audio_route *ar,
196 audio_usecase_t usecase,
197 snd_device_t snd_device)
198{
199 ALOGV("%s: enter: usecase(%d) snd_device(%d)",
200 __func__, usecase, snd_device);
201 char mixer_path[50];
202 strcpy(mixer_path, use_case_table[usecase]);
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800203 add_backend_name(mixer_path, snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800204 audio_route_apply_path(ar, mixer_path);
205 ALOGV("%s: exit", __func__);
206 return 0;
207}
208
209static int disable_audio_route(struct audio_route *ar,
210 audio_usecase_t usecase,
211 snd_device_t snd_device)
212{
213 ALOGV("%s: enter: usecase(%d) snd_device(%d)",
214 __func__, usecase, snd_device);
215 char mixer_path[50];
216 strcpy(mixer_path, use_case_table[usecase]);
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800217 add_backend_name(mixer_path, snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800218 audio_route_reset_path(ar, mixer_path);
219 ALOGV("%s: exit", __func__);
220 return 0;
221}
222
223static int enable_snd_device(struct audio_device *adev,
224 snd_device_t snd_device)
225{
226 int acdb_dev_id, acdb_dev_type;
227
228 ALOGV("%s: enter: snd_device(%d)", __func__, snd_device);
229 acdb_dev_id = get_acdb_device_id(snd_device);
230 if (acdb_dev_id < 0) {
231 ALOGE("%s: Could not find acdb id for device(%d)",
232 __func__, snd_device);
233 return -EINVAL;
234 }
235 if (snd_device >= SND_DEVICE_OUT_BEGIN &&
236 snd_device < SND_DEVICE_OUT_END) {
237 acdb_dev_type = ACDB_DEV_TYPE_OUT;
238 } else {
239 acdb_dev_type = ACDB_DEV_TYPE_IN;
240 }
241 if (adev->acdb_send_audio_cal) {
242 ALOGV("%s: sending audio calibration for snd_device(%d) acdb_id(%d)",
243 __func__, snd_device, acdb_dev_id);
244 adev->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type);
245 } else {
246 ALOGW("%s: Could find the symbol acdb_send_audio_cal from %s",
247 __func__, LIB_ACDB_LOADER);
248 }
249
250 audio_route_apply_path(adev->audio_route, device_table[snd_device]);
251 ALOGV("%s: exit", __func__);
252 return 0;
253}
254
255static int disable_snd_device(struct audio_route *ar,
256 snd_device_t snd_device)
257{
258 ALOGV("%s: enter: snd_device(%d)", __func__, snd_device);
259 audio_route_reset_path(ar, device_table[snd_device]);
260 ALOGV("%s: exit", __func__);
261 return 0;
262}
263
264static int set_hdmi_channels(struct mixer *mixer,
265 int channel_count)
266{
267 struct mixer_ctl *ctl;
268 const char *channel_cnt_str = NULL;
269 const char *mixer_ctl_name = "HDMI_RX Channels";
270 switch (channel_count) {
271 case 8:
272 channel_cnt_str = "Eight"; break;
273 case 7:
274 channel_cnt_str = "Seven"; break;
275 case 6:
276 channel_cnt_str = "Six"; break;
277 case 5:
278 channel_cnt_str = "Five"; break;
279 case 4:
280 channel_cnt_str = "Four"; break;
281 case 3:
282 channel_cnt_str = "Three"; break;
283 default:
284 channel_cnt_str = "Two"; break;
285 }
286 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
287 if (!ctl) {
288 ALOGE("%s: Could not get ctl for mixer cmd - %s",
289 __func__, mixer_ctl_name);
290 return -EINVAL;
291 }
292 ALOGV("HDMI channel count: %s", channel_cnt_str);
293 mixer_ctl_set_enum_by_string(ctl, channel_cnt_str);
294 return 0;
295}
296
297/* must be called with hw device mutex locked */
298static void read_hdmi_channel_masks(struct stream_out *out)
299{
300 int channels = edid_get_max_channels();
301 ALOGE("%s: enter", __func__);
302
303 switch (channels) {
304 /*
305 * Do not handle stereo output in Multi-channel cases
306 * Stereo case is handled in normal playback path
307 */
308 case 6:
309 ALOGV("%s: HDMI supports 5.1", __func__);
310 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
311 break;
312 case 8:
313 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
314 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
315 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
316 break;
317 default:
318 ALOGE("Unsupported number of channels (%d)", channels);
319 break;
320 }
321
322 ALOGE("%s: exit", __func__);
323}
324
325static snd_device_t get_output_snd_device(struct audio_device *adev)
326{
Eric Laurentc8400632013-02-14 19:04:54 -0800327 audio_source_t source = (adev->active_input == NULL) ?
328 AUDIO_SOURCE_DEFAULT : adev->active_input->source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800329 audio_mode_t mode = adev->mode;
330 audio_devices_t devices = adev->out_device;
331 snd_device_t snd_device = SND_DEVICE_INVALID;
332
333 ALOGV("%s: enter: output devices(0x%x)", __func__, devices);
334 if (devices == AUDIO_DEVICE_NONE ||
335 devices & AUDIO_DEVICE_BIT_IN) {
336 ALOGV("%s: Invalid output devices (0x%x)", __func__, devices);
337 goto exit;
338 }
339
340 if (mode == AUDIO_MODE_IN_CALL) {
341 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
342 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800343 if (adev->tty_mode == TTY_MODE_FULL)
344 snd_device = SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES;
345 else if (adev->tty_mode == TTY_MODE_VCO)
346 snd_device = SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES;
347 else if (adev->tty_mode == TTY_MODE_HCO)
348 snd_device = SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET;
349 else
350 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800351 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
352 snd_device = SND_DEVICE_OUT_BT_SCO;
353 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
354 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
355 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800356 if (adev->is_tmus)
357 snd_device = SND_DEVICE_OUT_VOICE_HANDSET_TMUS;
358 else
359 snd_device = SND_DEVICE_OUT_HANDSET;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800360 }
361 if (snd_device != SND_DEVICE_INVALID) {
362 goto exit;
363 }
364 }
365
366 if (popcount(devices) == 2) {
367 if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
368 AUDIO_DEVICE_OUT_SPEAKER)) {
369 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
370 } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
371 AUDIO_DEVICE_OUT_SPEAKER)) {
372 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
373 } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL |
374 AUDIO_DEVICE_OUT_SPEAKER)) {
375 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
376 } else {
377 ALOGE("%s: Invalid combo device(0x%x)", __func__, devices);
378 goto exit;
379 }
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800380 if (snd_device != SND_DEVICE_INVALID) {
381 goto exit;
382 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800383 }
384 if (popcount(devices) != 1) {
385 ALOGE("%s: Invalid output devices(0x%x)", __func__, devices);
386 goto exit;
387 }
388
389 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
390 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
391 snd_device = SND_DEVICE_OUT_HEADPHONES;
392 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
393 snd_device = SND_DEVICE_OUT_SPEAKER;
394 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
395 snd_device = SND_DEVICE_OUT_BT_SCO;
396 } else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
397 snd_device = SND_DEVICE_OUT_HDMI ;
398 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
399 snd_device = SND_DEVICE_OUT_HANDSET;
400 } else {
401 ALOGE("%s: Unknown device(s) 0x%x", __func__, devices);
402 }
403exit:
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800404 ALOGV("%s: exit: snd_device(%s)", __func__,
405 (snd_device == SND_DEVICE_INVALID) ?
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800406 "none" : device_table[snd_device]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800407 return snd_device;
408}
409
410static snd_device_t get_input_snd_device(struct audio_device *adev)
411{
Eric Laurentc8400632013-02-14 19:04:54 -0800412 audio_source_t source = (adev->active_input == NULL) ?
413 AUDIO_SOURCE_DEFAULT : adev->active_input->source;
414
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800415 audio_mode_t mode = adev->mode;
416 audio_devices_t out_device = adev->out_device;
Eric Laurentc8400632013-02-14 19:04:54 -0800417 audio_devices_t in_device = ((adev->active_input == NULL) ?
418 AUDIO_DEVICE_NONE : adev->active_input->device)
419 & ~AUDIO_DEVICE_BIT_IN;
420 audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
421 AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800422 snd_device_t snd_device = SND_DEVICE_INVALID;
423
424 ALOGV("%s: enter: out_device(0x%x) in_device(0x%x)",
425 __func__, out_device, in_device);
426 if (mode == AUDIO_MODE_IN_CALL) {
427 if (out_device == AUDIO_DEVICE_NONE) {
428 ALOGE("%s: No output device set for voice call", __func__);
429 goto exit;
430 }
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800431 if (adev->tty_mode != TTY_MODE_OFF) {
432 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
433 out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
434 switch (adev->tty_mode) {
435 case TTY_MODE_FULL:
436 snd_device = SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC;
437 break;
438 case TTY_MODE_VCO:
439 snd_device = SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC;
440 break;
441 case TTY_MODE_HCO:
442 snd_device = SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC;
443 break;
444 default:
445 ALOGE("%s: Invalid TTY mode (0x%x)", __func__, adev->tty_mode);
446 }
447 goto exit;
448 }
449 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800450 if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
451 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800452 if (adev->mic_type_analog || adev->fluence_in_voice_call == false) {
453 snd_device = SND_DEVICE_IN_HANDSET_MIC;
454 } else {
455 if (adev->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
456 if (adev->is_tmus)
457 snd_device = SND_DEVICE_IN_VOICE_DMIC_EF_TMUS;
458 else
459 snd_device = SND_DEVICE_IN_VOICE_DMIC_EF;
460 } else if(adev->dualmic_config == DUALMIC_CONFIG_BROADSIDE)
461 snd_device = SND_DEVICE_IN_VOICE_DMIC_BS;
462 else
463 snd_device = SND_DEVICE_IN_HANDSET_MIC;
464 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800465 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
466 snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
467 } else if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
468 snd_device = SND_DEVICE_IN_BT_SCO_MIC ;
469 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800470 if (adev->fluence_in_voice_call &&
471 adev->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
472 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF;
473 } else if (adev->fluence_in_voice_call &&
474 adev->dualmic_config == DUALMIC_CONFIG_BROADSIDE) {
475 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS;
476 } else {
477 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
478 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800479 }
480 } else if (source == AUDIO_SOURCE_CAMCORDER) {
481 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
482 in_device & AUDIO_DEVICE_IN_BACK_MIC) {
483 snd_device = SND_DEVICE_IN_CAMCORDER_MIC;
484 }
485 } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) {
486 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
Eric Laurentc8400632013-02-14 19:04:54 -0800487 if (adev->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
488 if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
489 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_EF;
490 else if (adev->fluence_in_voice_rec)
491 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE;
492 else
493 snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
494 } else if (adev->dualmic_config == DUALMIC_CONFIG_BROADSIDE) {
495 if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
496 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_BS;
497 else if (adev->fluence_in_voice_rec)
498 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE;
499 else
500 snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
501 } else
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800502 snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800503 }
Ravi Kumar Alamanda8455fa72013-02-19 14:53:19 -0800504 } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
505 if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
506 in_device = AUDIO_DEVICE_IN_BACK_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800507 } else if (source == AUDIO_SOURCE_DEFAULT) {
508 goto exit;
509 }
510
511 if (snd_device != SND_DEVICE_INVALID) {
512 goto exit;
513 }
514
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800515 if (in_device != AUDIO_DEVICE_NONE &&
Ravi Kumar Alamanda8455fa72013-02-19 14:53:19 -0800516 !(in_device & AUDIO_DEVICE_IN_VOICE_CALL) &&
517 !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800518 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800519 snd_device = SND_DEVICE_IN_HANDSET_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800520 } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800521 if (adev->mic_type_analog)
522 snd_device = SND_DEVICE_IN_HANDSET_MIC;
523 else
524 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800525 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
526 snd_device = SND_DEVICE_IN_HEADSET_MIC;
527 } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
528 snd_device = SND_DEVICE_IN_BT_SCO_MIC ;
529 } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) {
530 snd_device = SND_DEVICE_IN_HDMI_MIC;
531 } else {
532 ALOGE("%s: Unknown input device(s) 0x%x", __func__, in_device);
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800533 ALOGW("%s: Using default handset-mic", __func__);
534 snd_device = SND_DEVICE_IN_HANDSET_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800535 }
536 } else {
537 if (out_device & AUDIO_DEVICE_OUT_EARPIECE) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800538 snd_device = SND_DEVICE_IN_HANDSET_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800539 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
540 snd_device = SND_DEVICE_IN_HEADSET_MIC;
541 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
542 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
543 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800544 snd_device = SND_DEVICE_IN_HANDSET_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800545 } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800546 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800547 } else if (out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
548 snd_device = SND_DEVICE_IN_HDMI_MIC;
549 } else {
550 ALOGE("%s: Unknown output device(s) 0x%x", __func__, out_device);
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800551 ALOGW("%s: Using default handset-mic", __func__);
552 snd_device = SND_DEVICE_IN_HANDSET_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800553 }
554 }
555exit:
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800556 ALOGV("%s: exit: in_snd_device(%s)", __func__,
557 (snd_device == SND_DEVICE_INVALID) ?
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800558 "none" : device_table[snd_device]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800559 return snd_device;
560}
561
562static int select_devices(struct audio_device *adev)
563{
564 snd_device_t out_snd_device = SND_DEVICE_INVALID;
565 snd_device_t in_snd_device = SND_DEVICE_INVALID;
566 struct audio_usecase *usecase;
567 int status = 0;
568 int acdb_rx_id, acdb_tx_id;
569 bool in_call_device_switch = false;
570
571 ALOGV("%s: enter", __func__);
572 out_snd_device = get_output_snd_device(adev);
573 in_snd_device = get_input_snd_device(adev);
574
575 if (out_snd_device == adev->cur_out_snd_device && adev->out_snd_device_active &&
576 in_snd_device == adev->cur_in_snd_device && adev->in_snd_device_active) {
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800577 ALOGV("%s: exit: snd_devices (%d and %d) are already active",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800578 __func__, out_snd_device, in_snd_device);
579 return 0;
580 }
581
582 /*
583 * Limitation: While in call, to do a device switch we need to disable
584 * and enable both RX and TX devices though one of them is same as current
585 * device.
586 */
Ravi Kumar Alamanda778bf122013-02-20 16:59:34 -0800587 if (adev->in_call && adev->csd_client != NULL) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800588 in_call_device_switch = true;
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800589 /* This must be called before disabling the mixer controls on APQ side */
590 if (adev->csd_disable_device == NULL) {
Ravi Kumar Alamanda778bf122013-02-20 16:59:34 -0800591 ALOGE("%s: dlsym error for csd_client_disable_device", __func__);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800592 } else {
593 status = adev->csd_disable_device();
594 if (status < 0) {
595 ALOGE("%s: csd_client_disable_device, failed, error %d",
596 __func__, status);
597 }
598 }
599 }
600
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800601 if ((out_snd_device != adev->cur_out_snd_device || in_call_device_switch)
602 && adev->out_snd_device_active) {
603 usecase = &adev->usecase_list;
604 while (usecase->next != NULL) {
605 usecase = usecase->next;
606 if (usecase->type == PCM_PLAYBACK || usecase->type == VOICE_CALL) {
607 disable_audio_route(adev->audio_route, usecase->id,
608 adev->cur_out_snd_device);
609 }
610 }
611 audio_route_update_mixer(adev->audio_route);
612 /* Disable current rx device */
613 disable_snd_device(adev->audio_route, adev->cur_out_snd_device);
614 adev->out_snd_device_active = false;
615 }
616
617 if ((in_snd_device != adev->cur_in_snd_device || in_call_device_switch)
618 && adev->in_snd_device_active) {
619 usecase = &adev->usecase_list;
620 while (usecase->next != NULL) {
621 usecase = usecase->next;
622 if (usecase->type == PCM_CAPTURE) {
623 disable_audio_route(adev->audio_route, usecase->id,
624 adev->cur_in_snd_device);
625 }
626 }
627 audio_route_update_mixer(adev->audio_route);
628 /* Disable current tx device */
629 disable_snd_device(adev->audio_route, adev->cur_in_snd_device);
630 adev->in_snd_device_active = false;
631 }
632
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800633 if (out_snd_device != SND_DEVICE_INVALID && !adev->out_snd_device_active) {
634 /* Enable new rx device */
635 status = enable_snd_device(adev, out_snd_device);
636 if (status != 0) {
637 ALOGE("%s: Failed to set mixer ctls for snd_device(%d)",
638 __func__, out_snd_device);
639 return status;
640 }
641 adev->out_snd_device_active = true;
642 adev->cur_out_snd_device = out_snd_device;
643 }
644
645 if (in_snd_device != SND_DEVICE_INVALID && !adev->in_snd_device_active) {
646 /* Enable new tx device */
647 status = enable_snd_device(adev, in_snd_device);
648 if (status != 0) {
649 ALOGE("%s: Failed to set mixer ctls for snd_device(%d)",
650 __func__, out_snd_device);
651 return status;
652 }
653 adev->in_snd_device_active = true;
654 adev->cur_in_snd_device = in_snd_device;
655 }
656 audio_route_update_mixer(adev->audio_route);
657
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800658 usecase = &adev->usecase_list;
659 while (usecase->next != NULL) {
660 usecase = usecase->next;
661 if (usecase->type == PCM_PLAYBACK || usecase->type == VOICE_CALL) {
662 usecase->devices = adev->out_device; /* TODO: fix device logic */
663 status = enable_audio_route(adev->audio_route, usecase->id,
664 adev->cur_out_snd_device);
665 } else {
666 status = enable_audio_route(adev->audio_route, usecase->id,
667 adev->cur_in_snd_device);
668 }
669 }
670 audio_route_update_mixer(adev->audio_route);
671
Ravi Kumar Alamanda778bf122013-02-20 16:59:34 -0800672 if (adev->mode == AUDIO_MODE_IN_CALL && adev->csd_client) {
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800673 if (adev->csd_enable_device == NULL) {
674 ALOGE("%s: dlsym error for csd_client_enable_device",
675 __func__);
676 } else {
677 acdb_rx_id = get_acdb_device_id(out_snd_device);
678 acdb_tx_id = get_acdb_device_id(in_snd_device);
679
Ravi Kumar Alamanda778bf122013-02-20 16:59:34 -0800680 status = adev->csd_enable_device(acdb_rx_id, acdb_tx_id,
681 adev->acdb_settings);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800682 if (status < 0) {
683 ALOGE("%s: csd_client_enable_device, failed, error %d",
684 __func__, status);
685 }
686 }
687 }
688
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800689 ALOGV("%s: exit: status(%d)", __func__, status);
690 return status;
691}
692
693static void add_usecase_to_list(struct audio_device *adev,
694 struct audio_usecase *uc_info)
695{
696 struct audio_usecase *first_entry = adev->usecase_list.next;
697 ALOGV("%s: enter: usecase(%d)", __func__, uc_info->id);
698 /* Insert the new entry on the top of the list */
699 adev->usecase_list.next = uc_info;
700 uc_info->next = first_entry;
701 ALOGV("%s: exit", __func__);
702}
703
704static void remove_usecase_from_list(struct audio_device *adev,
705 audio_usecase_t uc_id)
706{
707 struct audio_usecase *uc_to_remove = NULL;
708 struct audio_usecase *list_head = &adev->usecase_list;
709 ALOGV("%s: enter: usecase(%d)", __func__, uc_id);
710 while (list_head->next != NULL) {
711 if (list_head->next->id == uc_id) {
712 uc_to_remove = list_head->next;
713 list_head->next = list_head->next->next;
714 free(uc_to_remove);
715 break;
716 }
717 list_head = list_head->next;
718 }
719 ALOGV("%s: exit", __func__);
720}
721
722static struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
723 audio_usecase_t uc_id)
724{
725 struct audio_usecase *uc_info = NULL;
726 struct audio_usecase *list_head = &adev->usecase_list;
727 ALOGV("%s: enter: uc_id(%d)", __func__, uc_id);
728 while (list_head->next != NULL) {
729 list_head = list_head->next;
730 if (list_head->id == uc_id) {
731 uc_info = list_head;
732 break;
733 }
734 }
735 ALOGV("%s: exit: uc_info(%p)", __func__, uc_info);
736 return uc_info;
737}
738
739static int get_num_active_usecases(struct audio_device *adev)
740{
741 int num_uc = 0;
742 struct audio_usecase *list_head = &adev->usecase_list;
743 while (list_head->next != NULL) {
744 num_uc++;
745 list_head = list_head->next;
746 }
747 return num_uc;
748}
749
750static audio_devices_t get_active_out_devices(struct audio_device *adev,
751 audio_usecase_t usecase)
752{
753 audio_devices_t devices = 0;
754 struct audio_usecase *list_head = &adev->usecase_list;
755 /* Return the output devices of usecases other than given usecase */
756 while (list_head->next != NULL) {
757 list_head = list_head->next;
758 if (list_head->type == PCM_PLAYBACK && list_head->id != usecase) {
759 devices |= list_head->devices;
760 }
761 }
762 return devices;
763}
764
765static audio_devices_t get_voice_call_out_device(struct audio_device *adev)
766{
767 audio_devices_t devices = 0;
768 struct audio_usecase *list_head = &adev->usecase_list;
Ravi Kumar Alamanda778bf122013-02-20 16:59:34 -0800769 /* Return the output devices of usecases other than VOICE_CALL usecase */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800770 while (list_head->next != NULL) {
771 list_head = list_head->next;
772 if (list_head->id == USECASE_VOICE_CALL) {
773 devices = list_head->devices;
774 break;
775 }
776 }
777 return devices;
778}
779
780static int stop_input_stream(struct stream_in *in)
781{
782 int i, ret = 0;
783 snd_device_t in_snd_device;
784 struct audio_usecase *uc_info;
785 struct audio_device *adev = in->dev;
786
Eric Laurentc8400632013-02-14 19:04:54 -0800787 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800788
Eric Laurentc8400632013-02-14 19:04:54 -0800789 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800790 uc_info = get_usecase_from_list(adev, in->usecase);
791 if (uc_info == NULL) {
792 ALOGE("%s: Could not find the usecase (%d) in the list",
793 __func__, in->usecase);
794 return -EINVAL;
795 }
796
797 /* 1. Close the PCM device first */
798 if (in->pcm) {
799 pcm_close(in->pcm);
800 in->pcm = NULL;
801 }
802
803 /* 2. Disable stream specific mixer controls */
804 in_snd_device = adev->cur_in_snd_device;
805 disable_audio_route(adev->audio_route, in->usecase, in_snd_device);
806 audio_route_update_mixer(adev->audio_route);
807
808 remove_usecase_from_list(adev, in->usecase);
809
810 /* 3. Disable the tx device */
811 select_devices(adev);
812
813 ALOGV("%s: exit: status(%d)", __func__, ret);
814 return ret;
815}
816
817int start_input_stream(struct stream_in *in)
818{
819 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -0800820 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800821 snd_device_t in_snd_device;
822 struct audio_usecase *uc_info;
823 struct audio_device *adev = in->dev;
824
825 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -0800826 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800827 in_snd_device = get_input_snd_device(adev);
828 if (in_snd_device == SND_DEVICE_INVALID) {
829 ALOGE("%s: Could not get valid input sound device", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -0800830 ret = -EINVAL;
831 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800832 }
833
834 in->pcm_device_id = get_pcm_device_id(adev->audio_route,
835 in->usecase,
836 PCM_CAPTURE);
837 if (in->pcm_device_id < 0) {
838 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
839 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -0800840 ret = -EINVAL;
841 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800842 }
843 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
844 uc_info->id = in->usecase;
845 uc_info->type = PCM_CAPTURE;
846 uc_info->devices = in->device;
847
848 /* 1. Enable the TX device */
849 ret = select_devices(adev);
850 if (ret) {
851 ALOGE("%s: Failed to enable device(0x%x)",
Eric Laurentc8400632013-02-14 19:04:54 -0800852 __func__, in->device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800853 free(uc_info);
Eric Laurentc8400632013-02-14 19:04:54 -0800854 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800855 }
856 in_snd_device = adev->cur_in_snd_device;
857
858 /* 2. Enable the mixer controls for the audio route */
859 enable_audio_route(adev->audio_route, in->usecase, in_snd_device);
860 audio_route_update_mixer(adev->audio_route);
861
862 /* 3. Add the usecase info to usecase list */
863 add_usecase_to_list(adev, uc_info);
864
865 /* 2. Open the pcm device */
Eric Laurentc8400632013-02-14 19:04:54 -0800866 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
867 __func__, SOUND_CARD, in->pcm_device_id, in->config.channels);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800868 in->pcm = pcm_open(SOUND_CARD, in->pcm_device_id,
869 PCM_IN, &in->config);
870 if (in->pcm && !pcm_is_ready(in->pcm)) {
871 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
872 pcm_close(in->pcm);
873 in->pcm = NULL;
Eric Laurentc8400632013-02-14 19:04:54 -0800874 ret = -EIO;
875 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800876 }
877 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -0800878 return ret;
879
880error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800881 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -0800882
883error_config:
884 adev->active_input = NULL;
885 ALOGV("%s: exit: status(%d)", __func__, ret);
886
887 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800888}
889
890static int stop_output_stream(struct stream_out *out)
891{
892 int i, ret = 0;
893 snd_device_t out_snd_device;
894 struct audio_usecase *uc_info;
895 struct audio_device *adev = out->dev;
896
897 ALOGV("%s: enter: usecase(%d)", __func__, out->usecase);
898 uc_info = get_usecase_from_list(adev, out->usecase);
899 if (uc_info == NULL) {
900 ALOGE("%s: Could not find the usecase (%d) in the list",
901 __func__, out->usecase);
902 return -EINVAL;
903 }
904
905 /* 1. Close the PCM device first */
906 if (out->pcm) {
907 pcm_close(out->pcm);
908 out->pcm = NULL;
909 }
910
911 /* 2. Get and set stream specific mixer controls */
912 out_snd_device = adev->cur_out_snd_device;
913 disable_audio_route(adev->audio_route, out->usecase, out_snd_device);
914 audio_route_update_mixer(adev->audio_route);
915
916 remove_usecase_from_list(adev, uc_info->id);
917
918 /* 3. Disable the rx device */
919 adev->out_device = get_active_out_devices(adev, out->usecase);
920 adev->out_device |= get_voice_call_out_device(adev);
921 ret = select_devices(adev);
922
923 ALOGV("%s: exit: status(%d)", __func__, ret);
924 return ret;
925}
926
927int start_output_stream(struct stream_out *out)
928{
929 int status;
930 int ret = 0;
931 snd_device_t out_snd_device;
932 struct audio_usecase *uc_info;
933 struct audio_device *adev = out->dev;
934
935 /* 1. Enable output device and stream routing controls */
936 ALOGV("%s: enter: usecase(%d)", __func__, out->usecase);
937 adev->out_device |= out->devices;
938 out_snd_device = get_output_snd_device(adev);
939 if (out_snd_device == SND_DEVICE_INVALID) {
940 ALOGE("%s: Could not get valid output sound device", __func__);
941 /*
942 * TODO: use a single exit point to avoid duplicating code to
943 * reset output device
944 */
945 adev->out_device = get_active_out_devices(adev, out->usecase);
946 adev->out_device |= get_voice_call_out_device(adev);
947 return -EINVAL;
948 }
949
950 out->pcm_device_id = get_pcm_device_id(adev->audio_route,
951 out->usecase,
952 PCM_PLAYBACK);
953 if (out->pcm_device_id < 0) {
954 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
955 __func__, out->pcm_device_id, out->usecase);
956 adev->out_device = get_active_out_devices(adev, out->usecase);
957 adev->out_device |= get_voice_call_out_device(adev);
958 return -EINVAL;
959 }
960
961 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
962 uc_info->id = out->usecase;
963 uc_info->type = PCM_PLAYBACK;
964 uc_info->devices = out->devices;
965
966 ret = select_devices(adev);
967 if (ret) {
968 ALOGE("%s: Failed to enable device(0x%x)",
969 __func__, adev->out_device);
970 adev->out_device = get_active_out_devices(adev, out->usecase);
971 adev->out_device |= get_voice_call_out_device(adev);
972 free(uc_info);
973 return ret;
974 }
975
976 out_snd_device = adev->cur_out_snd_device;
977 enable_audio_route(adev->audio_route, out->usecase, out_snd_device);
978 audio_route_update_mixer(adev->audio_route);
979
980 add_usecase_to_list(adev, uc_info);
981
982 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d)",
983 __func__, 0, out->pcm_device_id);
984 out->pcm = pcm_open(SOUND_CARD, out->pcm_device_id,
985 PCM_OUT, &out->config);
986 if (out->pcm && !pcm_is_ready(out->pcm)) {
987 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
988 pcm_close(out->pcm);
989 out->pcm = NULL;
990 status = -EIO;
991 goto error;
992 }
993 ALOGV("%s: exit", __func__);
994 return 0;
995error:
996 stop_output_stream(out);
997 ALOGE("%s: exit: status(%d)", __func__, status);
998 return status;
999}
1000
1001static int stop_voice_call(struct audio_device *adev)
1002{
1003 int i, ret = 0;
1004 snd_device_t out_snd_device;
1005 struct audio_usecase *uc_info;
1006
Ravi Kumar Alamanda778bf122013-02-20 16:59:34 -08001007 ALOGV("%s: enter", __func__);
1008 adev->in_call = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001009 if (adev->csd_client) {
1010 if (adev->csd_stop_voice == NULL) {
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001011 ALOGE("dlsym error for csd_client_disable_device");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001012 } else {
1013 ret = adev->csd_stop_voice();
1014 if (ret < 0) {
1015 ALOGE("%s: csd_client error %d\n", __func__, ret);
1016 }
1017 }
1018 }
1019
1020 /* 1. Close the PCM devices */
1021 if (adev->voice_call_rx) {
1022 pcm_close(adev->voice_call_rx);
1023 adev->voice_call_rx = NULL;
1024 }
1025 if (adev->voice_call_tx) {
1026 pcm_close(adev->voice_call_tx);
1027 adev->voice_call_tx = NULL;
1028 }
1029
1030 uc_info = get_usecase_from_list(adev, USECASE_VOICE_CALL);
1031 if (uc_info == NULL) {
1032 ALOGE("%s: Could not find the usecase (%d) in the list",
1033 __func__, USECASE_VOICE_CALL);
1034 return -EINVAL;
1035 }
1036 out_snd_device = adev->cur_out_snd_device;
1037
1038 /* 2. Get and set stream specific mixer controls */
1039 /* ToDo: Status check ?*/
1040 disable_audio_route(adev->audio_route, USECASE_VOICE_CALL, out_snd_device);
1041 audio_route_update_mixer(adev->audio_route);
1042
1043 remove_usecase_from_list(adev, uc_info->id);
1044
1045 /* 3. Disable the rx and tx devices */
1046 ret = select_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001047
1048 ALOGV("%s: exit: status(%d)", __func__, ret);
1049 return ret;
1050}
1051
1052static int start_voice_call(struct audio_device *adev)
1053{
1054 int i, ret = 0;
1055 snd_device_t out_snd_device;
1056 struct audio_usecase *uc_info;
1057 int pcm_dev_rx_id, pcm_dev_tx_id;
1058
1059 ALOGV("%s: enter", __func__);
1060
1061 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1062 uc_info->id = USECASE_VOICE_CALL;
1063 uc_info->type = VOICE_CALL;
1064 uc_info->devices = adev->out_device;
1065
1066 ret = select_devices(adev);
1067 if (ret) {
1068 free(uc_info);
1069 return ret;
1070 }
1071
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001072 out_snd_device = adev->cur_out_snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001073 enable_audio_route(adev->audio_route, uc_info->id, out_snd_device);
1074 audio_route_update_mixer(adev->audio_route);
1075
1076 add_usecase_to_list(adev, uc_info);
1077
1078 pcm_dev_rx_id = get_pcm_device_id(adev->audio_route, uc_info->id,
1079 PCM_PLAYBACK);
1080 pcm_dev_tx_id = get_pcm_device_id(adev->audio_route, uc_info->id,
1081 PCM_CAPTURE);
1082
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001083 if (pcm_dev_rx_id < 0 || pcm_dev_tx_id < 0) {
1084 ALOGE("%s: Invalid PCM devices (rx: %d tx: %d) for the usecase(%d)",
1085 __func__, pcm_dev_rx_id, pcm_dev_tx_id, uc_info->id);
Ravi Kumar Alamanda778bf122013-02-20 16:59:34 -08001086 ret = -EIO;
1087 goto error_start_voice;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001088 }
1089
Ravi Kumar Alamanda778bf122013-02-20 16:59:34 -08001090 ALOGV("%s: Opening PCM playback device card_id(%d) device_id(%d)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001091 __func__, SOUND_CARD, pcm_dev_rx_id);
1092 adev->voice_call_rx = pcm_open(SOUND_CARD,
1093 pcm_dev_rx_id,
1094 PCM_OUT, &pcm_config_voice_call);
1095 if (adev->voice_call_rx && !pcm_is_ready(adev->voice_call_rx)) {
1096 ALOGE("%s: %s", __func__, pcm_get_error(adev->voice_call_rx));
Ravi Kumar Alamanda778bf122013-02-20 16:59:34 -08001097 ret = -EIO;
1098 goto error_start_voice;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001099 }
1100
Ravi Kumar Alamanda778bf122013-02-20 16:59:34 -08001101 ALOGV("%s: Opening PCM capture device card_id(%d) device_id(%d)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001102 __func__, SOUND_CARD, pcm_dev_tx_id);
1103 adev->voice_call_tx = pcm_open(SOUND_CARD,
1104 pcm_dev_tx_id,
1105 PCM_IN, &pcm_config_voice_call);
1106 if (adev->voice_call_tx && !pcm_is_ready(adev->voice_call_tx)) {
1107 ALOGE("%s: %s", __func__, pcm_get_error(adev->voice_call_tx));
Ravi Kumar Alamanda778bf122013-02-20 16:59:34 -08001108 ret = -EIO;
1109 goto error_start_voice;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001110 }
1111 pcm_start(adev->voice_call_rx);
1112 pcm_start(adev->voice_call_tx);
1113
1114 if (adev->csd_client) {
1115 if (adev->csd_start_voice == NULL) {
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001116 ALOGE("dlsym error for csd_client_start_voice");
Ravi Kumar Alamanda778bf122013-02-20 16:59:34 -08001117 goto error_start_voice;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001118 } else {
1119 ret = adev->csd_start_voice();
1120 if (ret < 0) {
Ravi Kumar Alamanda778bf122013-02-20 16:59:34 -08001121 ALOGE("%s: csd_start_voice error %d\n", __func__, ret);
1122 goto error_start_voice;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001123 }
1124 }
1125 }
1126
1127 adev->in_call = true;
Ravi Kumar Alamanda778bf122013-02-20 16:59:34 -08001128 return 0;
1129
1130error_start_voice:
1131 stop_voice_call(adev);
1132
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001133 ALOGV("%s: exit: status(%d)", __func__, ret);
1134 return ret;
1135}
1136
1137static int check_input_parameters(uint32_t sample_rate,
1138 audio_format_t format,
1139 int channel_count)
1140{
1141 if (format != AUDIO_FORMAT_PCM_16_BIT) return -EINVAL;
1142
1143 if ((channel_count < 1) || (channel_count > 2)) return -EINVAL;
1144
1145 switch (sample_rate) {
1146 case 8000:
1147 case 11025:
1148 case 12000:
1149 case 16000:
1150 case 22050:
1151 case 24000:
1152 case 32000:
1153 case 44100:
1154 case 48000:
1155 break;
1156 default:
1157 return -EINVAL;
1158 }
1159
1160 return 0;
1161}
1162
1163static size_t get_input_buffer_size(uint32_t sample_rate,
1164 audio_format_t format,
1165 int channel_count)
1166{
1167 size_t size = 0;
1168
1169 if (check_input_parameters(sample_rate, format, channel_count) != 0) return 0;
1170
1171 if (sample_rate == 8000 || sample_rate == 16000 || sample_rate == 32000) {
1172 size = (sample_rate * 20) / 1000;
1173 } else if (sample_rate == 11025 || sample_rate == 12000) {
1174 size = 256;
1175 } else if (sample_rate == 22050 || sample_rate == 24000) {
1176 size = 512;
1177 } else if (sample_rate == 44100 || sample_rate == 48000) {
1178 size = 1024;
1179 }
1180
1181 return size * sizeof(short) * channel_count;
1182}
1183
1184static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1185{
1186 struct stream_out *out = (struct stream_out *)stream;
1187
1188 return out->config.rate;
1189}
1190
1191static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
1192{
1193 return -ENOSYS;
1194}
1195
1196static size_t out_get_buffer_size(const struct audio_stream *stream)
1197{
1198 struct stream_out *out = (struct stream_out *)stream;
1199
1200 return out->config.period_size * audio_stream_frame_size(stream);
1201}
1202
1203static uint32_t out_get_channels(const struct audio_stream *stream)
1204{
1205 struct stream_out *out = (struct stream_out *)stream;
1206
1207 return out->channel_mask;
1208}
1209
1210static audio_format_t out_get_format(const struct audio_stream *stream)
1211{
1212 return AUDIO_FORMAT_PCM_16_BIT;
1213}
1214
1215static int out_set_format(struct audio_stream *stream, audio_format_t format)
1216{
1217 return -ENOSYS;
1218}
1219
1220static int out_standby(struct audio_stream *stream)
1221{
1222 struct stream_out *out = (struct stream_out *)stream;
1223 struct audio_device *adev = out->dev;
1224 ALOGV("%s: enter: usecase(%d)", __func__, out->usecase);
1225 pthread_mutex_lock(&out->dev->lock);
1226 pthread_mutex_lock(&out->lock);
1227
1228 if (!out->standby) {
1229 out->standby = true;
1230 stop_output_stream(out);
1231 }
1232 pthread_mutex_unlock(&out->lock);
1233 pthread_mutex_unlock(&out->dev->lock);
1234 ALOGV("%s: exit", __func__);
1235 return 0;
1236}
1237
1238static int out_dump(const struct audio_stream *stream, int fd)
1239{
1240 return 0;
1241}
1242
1243static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1244{
1245 struct stream_out *out = (struct stream_out *)stream;
1246 struct audio_device *adev = out->dev;
1247 struct str_parms *parms;
1248 char value[32];
1249 int ret, val = 0;
1250
1251 ALOGV("%s: enter: usecase(%d) kvpairs: %s",
1252 __func__, out->usecase, kvpairs);
1253 parms = str_parms_create_str(kvpairs);
1254 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1255 if (ret >= 0) {
1256 val = atoi(value);
1257 pthread_mutex_lock(&adev->lock);
1258 pthread_mutex_lock(&out->lock);
1259
Ravi Kumar Alamanda8455fa72013-02-19 14:53:19 -08001260 if (adev->mode == AUDIO_MODE_IN_CALL && !adev->in_call && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001261 adev->out_device = get_active_out_devices(adev, out->usecase) | val;
Ravi Kumar Alamanda8455fa72013-02-19 14:53:19 -08001262 out->devices = val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001263 start_voice_call(adev);
1264 } else if (adev->mode != AUDIO_MODE_IN_CALL && adev->in_call) {
Ravi Kumar Alamanda8455fa72013-02-19 14:53:19 -08001265 if (val != 0) {
1266 adev->out_device = get_active_out_devices(adev, out->usecase) | val;
1267 out->devices = val;
1268 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001269 stop_voice_call(adev);
1270 } else if ((adev->out_device != (audio_devices_t)val) && (val != 0)) {
1271 if (!out->standby || adev->in_call) {
1272 adev->out_device = get_active_out_devices(adev, out->usecase) | val;
1273 ret = select_devices(adev);
1274 }
Ravi Kumar Alamanda778bf122013-02-20 16:59:34 -08001275 out->devices = val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001276 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001277
1278 pthread_mutex_unlock(&out->lock);
1279 pthread_mutex_unlock(&adev->lock);
1280 }
1281 str_parms_destroy(parms);
1282 ALOGV("%s: exit: code(%d)", __func__, ret);
1283 return ret;
1284}
1285
1286static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1287{
1288 struct stream_out *out = (struct stream_out *)stream;
1289 struct str_parms *query = str_parms_create_str(keys);
1290 char *str;
1291 char value[256];
1292 struct str_parms *reply = str_parms_create();
1293 size_t i, j;
1294 int ret;
1295 bool first = true;
1296 ALOGV("%s: enter: keys - %s", __func__, keys);
1297 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1298 if (ret >= 0) {
1299 value[0] = '\0';
1300 i = 0;
1301 while (out->supported_channel_masks[i] != 0) {
1302 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1303 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1304 if (!first) {
1305 strcat(value, "|");
1306 }
1307 strcat(value, out_channels_name_to_enum_table[j].name);
1308 first = false;
1309 break;
1310 }
1311 }
1312 i++;
1313 }
1314 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1315 str = str_parms_to_str(reply);
1316 } else {
1317 str = strdup(keys);
1318 }
1319 str_parms_destroy(query);
1320 str_parms_destroy(reply);
1321 ALOGV("%s: exit: returns - %s", __func__, str);
1322 return str;
1323}
1324
1325static uint32_t out_get_latency(const struct audio_stream_out *stream)
1326{
1327 struct stream_out *out = (struct stream_out *)stream;
1328
1329 return (out->config.period_count * out->config.period_size * 1000) / (out->config.rate);
1330}
1331
1332static int out_set_volume(struct audio_stream_out *stream, float left,
1333 float right)
1334{
1335 return -ENOSYS;
1336}
1337
1338static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
1339 size_t bytes)
1340{
1341 struct stream_out *out = (struct stream_out *)stream;
1342 struct audio_device *adev = out->dev;
1343 int i, ret = -1;
1344
1345 /* acquiring hw device mutex systematically is useful if a low priority thread is waiting
1346 * on the output stream mutex - e.g. executing select_mode() while holding the hw device
1347 * mutex
1348 */
1349 pthread_mutex_lock(&adev->lock);
1350 pthread_mutex_lock(&out->lock);
1351 if (out->standby) {
1352 ret = start_output_stream(out);
1353 if (ret != 0) {
1354 pthread_mutex_unlock(&adev->lock);
1355 goto exit;
1356 }
1357 out->standby = false;
1358 }
1359 pthread_mutex_unlock(&adev->lock);
1360
1361 if (out->pcm) {
1362 //ALOGV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
1363 ret = pcm_write(out->pcm, (void *)buffer, bytes);
1364 }
1365
1366exit:
1367 pthread_mutex_unlock(&out->lock);
1368
1369 if (ret != 0) {
1370 out_standby(&out->stream.common);
1371 usleep(bytes * 1000000 / audio_stream_frame_size(&out->stream.common) /
1372 out_get_sample_rate(&out->stream.common));
1373 }
1374 return bytes;
1375}
1376
1377static int out_get_render_position(const struct audio_stream_out *stream,
1378 uint32_t *dsp_frames)
1379{
1380 return -EINVAL;
1381}
1382
1383static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1384{
1385 return 0;
1386}
1387
1388static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1389{
1390 return 0;
1391}
1392
1393static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
1394 int64_t *timestamp)
1395{
1396 return -EINVAL;
1397}
1398
1399/** audio_stream_in implementation **/
1400static uint32_t in_get_sample_rate(const struct audio_stream *stream)
1401{
1402 struct stream_in *in = (struct stream_in *)stream;
1403
1404 return in->config.rate;
1405}
1406
1407static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
1408{
1409 return -ENOSYS;
1410}
1411
1412static size_t in_get_buffer_size(const struct audio_stream *stream)
1413{
1414 struct stream_in *in = (struct stream_in *)stream;
1415
1416 return in->config.period_size * audio_stream_frame_size(stream);
1417}
1418
1419static uint32_t in_get_channels(const struct audio_stream *stream)
1420{
1421 struct stream_in *in = (struct stream_in *)stream;
1422
1423 return in->channel_mask;
1424}
1425
1426static audio_format_t in_get_format(const struct audio_stream *stream)
1427{
1428 return AUDIO_FORMAT_PCM_16_BIT;
1429}
1430
1431static int in_set_format(struct audio_stream *stream, audio_format_t format)
1432{
1433 return -ENOSYS;
1434}
1435
1436static int in_standby(struct audio_stream *stream)
1437{
1438 struct stream_in *in = (struct stream_in *)stream;
1439 struct audio_device *adev = in->dev;
1440 int status = 0;
1441 ALOGV("%s: enter", __func__);
1442 pthread_mutex_lock(&adev->lock);
1443 pthread_mutex_lock(&in->lock);
1444 if (!in->standby) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001445 in->standby = true;
1446 status = stop_input_stream(in);
1447 }
1448 pthread_mutex_unlock(&in->lock);
1449 pthread_mutex_unlock(&adev->lock);
1450 ALOGV("%s: exit: status(%d)", __func__, status);
1451 return status;
1452}
1453
1454static int in_dump(const struct audio_stream *stream, int fd)
1455{
1456 return 0;
1457}
1458
1459static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
1460{
1461 struct stream_in *in = (struct stream_in *)stream;
1462 struct audio_device *adev = in->dev;
1463 struct str_parms *parms;
1464 char *str;
1465 char value[32];
1466 int ret, val = 0;
1467
1468 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
1469 parms = str_parms_create_str(kvpairs);
1470
1471 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
1472
1473 pthread_mutex_lock(&adev->lock);
1474 pthread_mutex_lock(&in->lock);
1475 if (ret >= 0) {
1476 val = atoi(value);
1477 /* no audio source uses val == 0 */
1478 if ((in->source != val) && (val != 0)) {
1479 in->source = val;
1480 }
1481 }
1482
1483 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1484 if (ret >= 0) {
1485 val = atoi(value);
1486 if ((in->device != val) && (val != 0)) {
1487 in->device = val;
1488 /* If recording is in progress, change the tx device to new device */
1489 if (!in->standby) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001490 ret = select_devices(adev);
1491 }
1492 }
1493 }
1494
1495 pthread_mutex_unlock(&in->lock);
1496 pthread_mutex_unlock(&adev->lock);
1497
1498 str_parms_destroy(parms);
1499 ALOGV("%s: exit: status(%d)", __func__, ret);
1500 return ret;
1501}
1502
1503static char* in_get_parameters(const struct audio_stream *stream,
1504 const char *keys)
1505{
1506 return strdup("");
1507}
1508
1509static int in_set_gain(struct audio_stream_in *stream, float gain)
1510{
1511 return 0;
1512}
1513
1514static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
1515 size_t bytes)
1516{
1517 struct stream_in *in = (struct stream_in *)stream;
1518 struct audio_device *adev = in->dev;
1519 int i, ret = -1;
1520
1521 /* acquiring hw device mutex systematically is useful if a low priority thread is waiting
1522 * on the output stream mutex - e.g. executing select_mode() while holding the hw device
1523 * mutex
1524 */
1525 //ALOGV("%s: buffer(%p) bytes(%d)", __func__, buffer, bytes);
1526 pthread_mutex_lock(&adev->lock);
1527 pthread_mutex_lock(&in->lock);
1528 if (in->standby) {
1529 ret = start_input_stream(in);
1530 if (ret != 0) {
1531 pthread_mutex_unlock(&adev->lock);
1532 goto exit;
1533 }
1534 in->standby = 0;
1535 }
1536 pthread_mutex_unlock(&adev->lock);
1537
1538 if (in->pcm) {
1539 ret = pcm_read(in->pcm, buffer, bytes);
1540 }
1541
1542 /*
1543 * Instead of writing zeroes here, we could trust the hardware
1544 * to always provide zeroes when muted.
1545 */
1546 if (ret == 0 && adev->mic_mute)
1547 memset(buffer, 0, bytes);
1548
1549exit:
1550 pthread_mutex_unlock(&in->lock);
1551
1552 if (ret != 0) {
1553 in_standby(&in->stream.common);
1554 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
1555 usleep(bytes * 1000000 / audio_stream_frame_size(&in->stream.common) /
1556 in_get_sample_rate(&in->stream.common));
1557 }
1558 return bytes;
1559}
1560
1561static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
1562{
1563 return 0;
1564}
1565
1566static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1567{
1568 return 0;
1569}
1570
1571static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1572{
1573 return 0;
1574}
1575
1576static int adev_open_output_stream(struct audio_hw_device *dev,
1577 audio_io_handle_t handle,
1578 audio_devices_t devices,
1579 audio_output_flags_t flags,
1580 struct audio_config *config,
1581 struct audio_stream_out **stream_out)
1582{
1583 struct audio_device *adev = (struct audio_device *)dev;
1584 struct stream_out *out;
1585 int i, ret;
1586
1587 ALOGV("%s: enter: sample_rate(%d) channel_mask(0x%x) devices(0x%x) flags(0x%x)",
1588 __func__, config->sample_rate, config->channel_mask, devices, flags);
1589 *stream_out = NULL;
1590 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
1591
1592 if (devices == AUDIO_DEVICE_NONE)
1593 devices = AUDIO_DEVICE_OUT_SPEAKER;
1594
1595 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
1596 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
1597 out->flags = flags;
1598 out->devices = devices;
1599
1600 /* Init use case and pcm_config */
1601 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
1602 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1603 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
1604 out->config = pcm_config_hdmi_multi;
1605
1606 pthread_mutex_lock(&adev->lock);
1607 read_hdmi_channel_masks(out);
1608 pthread_mutex_unlock(&adev->lock);
1609
1610 if (config->sample_rate == 0) config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1611 if (config->channel_mask == 0) config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
1612 out->channel_mask = config->channel_mask;
1613 out->config.rate = config->sample_rate;
1614 out->config.channels = popcount(out->channel_mask);
1615 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
1616 set_hdmi_channels(adev->mixer, out->config.channels);
1617 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
1618 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
1619 out->config = pcm_config_deep_buffer;
1620 } else {
1621 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
1622 out->config = pcm_config_low_latency;
1623 }
1624
1625 /* Check if this usecase is already existing */
1626 pthread_mutex_lock(&adev->lock);
1627 if (get_usecase_from_list(adev, out->usecase) != NULL) {
1628 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
1629 free(out);
1630 *stream_out = NULL;
1631 pthread_mutex_unlock(&adev->lock);
1632 return -EEXIST;
1633 }
1634 pthread_mutex_unlock(&adev->lock);
1635
1636 out->stream.common.get_sample_rate = out_get_sample_rate;
1637 out->stream.common.set_sample_rate = out_set_sample_rate;
1638 out->stream.common.get_buffer_size = out_get_buffer_size;
1639 out->stream.common.get_channels = out_get_channels;
1640 out->stream.common.get_format = out_get_format;
1641 out->stream.common.set_format = out_set_format;
1642 out->stream.common.standby = out_standby;
1643 out->stream.common.dump = out_dump;
1644 out->stream.common.set_parameters = out_set_parameters;
1645 out->stream.common.get_parameters = out_get_parameters;
1646 out->stream.common.add_audio_effect = out_add_audio_effect;
1647 out->stream.common.remove_audio_effect = out_remove_audio_effect;
1648 out->stream.get_latency = out_get_latency;
1649 out->stream.set_volume = out_set_volume;
1650 out->stream.write = out_write;
1651 out->stream.get_render_position = out_get_render_position;
1652 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
1653
1654 out->dev = adev;
1655 out->standby = 1;
1656
1657 config->format = out->stream.common.get_format(&out->stream.common);
1658 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
1659 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
1660
1661 *stream_out = &out->stream;
1662 ALOGV("%s: exit", __func__);
1663 return 0;
1664}
1665
1666static void adev_close_output_stream(struct audio_hw_device *dev,
1667 struct audio_stream_out *stream)
1668{
1669 ALOGV("%s: enter", __func__);
1670 out_standby(&stream->common);
1671 free(stream);
1672 ALOGV("%s: exit", __func__);
1673}
1674
1675static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
1676{
1677 struct audio_device *adev = (struct audio_device *)dev;
1678 struct str_parms *parms;
1679 char *str;
1680 char value[32];
1681 int ret;
1682
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -08001683 ALOGV("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001684
1685 parms = str_parms_create_str(kvpairs);
1686 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_TTY_MODE, value, sizeof(value));
1687 if (ret >= 0) {
1688 int tty_mode;
1689
1690 if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_OFF) == 0)
1691 tty_mode = TTY_MODE_OFF;
1692 else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_VCO) == 0)
1693 tty_mode = TTY_MODE_VCO;
1694 else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_HCO) == 0)
1695 tty_mode = TTY_MODE_HCO;
1696 else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_FULL) == 0)
1697 tty_mode = TTY_MODE_FULL;
1698 else
1699 return -EINVAL;
1700
1701 pthread_mutex_lock(&adev->lock);
1702 if (tty_mode != adev->tty_mode) {
1703 adev->tty_mode = tty_mode;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08001704 adev->acdb_settings = (adev->acdb_settings & TTY_MODE_CLEAR) | tty_mode;
1705 if (adev->in_call)
1706 select_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001707 }
1708 pthread_mutex_unlock(&adev->lock);
1709 }
1710
1711 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
1712 if (ret >= 0) {
1713 /* When set to false, HAL should disable EC and NS
1714 * But it is currently not supported.
1715 */
1716 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
1717 adev->bluetooth_nrec = true;
1718 else
1719 adev->bluetooth_nrec = false;
1720 }
1721
1722 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
1723 if (ret >= 0) {
1724 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
1725 adev->screen_off = false;
1726 else
1727 adev->screen_off = true;
1728 }
1729
1730 str_parms_destroy(parms);
1731 ALOGV("%s: exit with code(%d)", __func__, ret);
1732 return ret;
1733}
1734
1735static char* adev_get_parameters(const struct audio_hw_device *dev,
1736 const char *keys)
1737{
1738 /* ToDo: Return requested params */
1739 return strdup("");
1740}
1741
1742static int adev_init_check(const struct audio_hw_device *dev)
1743{
1744 return 0;
1745}
1746
1747static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
1748{
1749 struct audio_device *adev = (struct audio_device *)dev;
1750 int vol, err = 0;
1751
1752 pthread_mutex_lock(&adev->lock);
1753 adev->voice_volume = volume;
1754 if (adev->mode == AUDIO_MODE_IN_CALL) {
1755 if (volume < 0.0) {
1756 volume = 0.0;
1757 } else if (volume > 1.0) {
1758 volume = 1.0;
1759 }
1760
1761 vol = lrint(volume * 100.0);
1762
1763 // Voice volume levels from android are mapped to driver volume levels as follows.
1764 // 0 -> 5, 20 -> 4, 40 ->3, 60 -> 2, 80 -> 1, 100 -> 0
1765 // So adjust the volume to get the correct volume index in driver
1766 vol = 100 - vol;
1767
1768 if (adev->csd_client) {
1769 if (adev->csd_volume == NULL) {
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001770 ALOGE("%s: dlsym error for csd_client_volume", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001771 } else {
1772 err = adev->csd_volume(vol);
1773 if (err < 0) {
1774 ALOGE("%s: csd_client error %d", __func__, err);
1775 }
1776 }
1777 } else {
1778 ALOGE("%s: No CSD Client present", __func__);
1779 }
1780 }
1781 pthread_mutex_unlock(&adev->lock);
1782 return err;
1783}
1784
1785static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
1786{
1787 return -ENOSYS;
1788}
1789
1790static int adev_get_master_volume(struct audio_hw_device *dev,
1791 float *volume)
1792{
1793 return -ENOSYS;
1794}
1795
1796static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
1797{
1798 return -ENOSYS;
1799}
1800
1801static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
1802{
1803 return -ENOSYS;
1804}
1805
1806static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
1807{
1808 struct audio_device *adev = (struct audio_device *)dev;
1809
1810 pthread_mutex_lock(&adev->lock);
1811 if (adev->mode != mode) {
1812 adev->mode = mode;
1813 }
1814 pthread_mutex_unlock(&adev->lock);
1815 return 0;
1816}
1817
1818static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
1819{
1820 struct audio_device *adev = (struct audio_device *)dev;
1821 int err = 0;
1822
1823 adev->mic_mute = state;
1824 if (adev->mode == AUDIO_MODE_IN_CALL) {
1825 if (adev->csd_client) {
1826 if (adev->csd_mic_mute == NULL) {
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001827 ALOGE("%s: dlsym error for csd_mic_mute", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001828 } else {
1829 err = adev->csd_mic_mute(state);
1830 if (err < 0) {
1831 ALOGE("%s: csd_client error %d", __func__, err);
1832 }
1833 }
1834 } else {
1835 ALOGE("%s: No CSD Client present", __func__);
1836 }
1837 }
1838 return err;
1839}
1840
1841static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
1842{
1843 struct audio_device *adev = (struct audio_device *)dev;
1844
1845 *state = adev->mic_mute;
1846
1847 return 0;
1848}
1849
1850static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
1851 const struct audio_config *config)
1852{
1853 size_t size;
1854 int channel_count = popcount(config->channel_mask);
1855
1856 return get_input_buffer_size(config->sample_rate, config->format, channel_count);
1857}
1858
1859static int adev_open_input_stream(struct audio_hw_device *dev,
1860 audio_io_handle_t handle,
1861 audio_devices_t devices,
1862 struct audio_config *config,
1863 struct audio_stream_in **stream_in)
1864{
1865 struct audio_device *adev = (struct audio_device *)dev;
1866 struct stream_in *in;
1867 int ret, buffer_size, frame_size;
1868 int channel_count = popcount(config->channel_mask);
1869
1870 ALOGV("%s: enter", __func__);
1871 *stream_in = NULL;
1872 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
1873 return -EINVAL;
1874
1875 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
1876
1877 in->stream.common.get_sample_rate = in_get_sample_rate;
1878 in->stream.common.set_sample_rate = in_set_sample_rate;
1879 in->stream.common.get_buffer_size = in_get_buffer_size;
1880 in->stream.common.get_channels = in_get_channels;
1881 in->stream.common.get_format = in_get_format;
1882 in->stream.common.set_format = in_set_format;
1883 in->stream.common.standby = in_standby;
1884 in->stream.common.dump = in_dump;
1885 in->stream.common.set_parameters = in_set_parameters;
1886 in->stream.common.get_parameters = in_get_parameters;
1887 in->stream.common.add_audio_effect = in_add_audio_effect;
1888 in->stream.common.remove_audio_effect = in_remove_audio_effect;
1889 in->stream.set_gain = in_set_gain;
1890 in->stream.read = in_read;
1891 in->stream.get_input_frames_lost = in_get_input_frames_lost;
1892
1893 in->device = devices;
1894 in->source = AUDIO_SOURCE_DEFAULT;
1895 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001896 in->standby = 1;
1897 in->channel_mask = config->channel_mask;
1898
1899 /* Update config params with the requested sample rate and channels */
1900 in->usecase = USECASE_AUDIO_RECORD;
1901 in->config = pcm_config_audio_capture;
1902 in->config.channels = channel_count;
1903 in->config.rate = config->sample_rate;
1904
1905 frame_size = audio_stream_frame_size((struct audio_stream *)in);
1906 buffer_size = get_input_buffer_size(config->sample_rate,
1907 config->format,
1908 channel_count);
1909 in->config.period_size = buffer_size / frame_size;
1910
1911 *stream_in = &in->stream;
1912 ALOGV("%s: exit", __func__);
1913 return 0;
1914
1915err_open:
1916 free(in);
1917 *stream_in = NULL;
1918 return ret;
1919}
1920
1921static void adev_close_input_stream(struct audio_hw_device *dev,
1922 struct audio_stream_in *stream)
1923{
1924 in_standby(&stream->common);
1925 free(stream);
1926
1927 return;
1928}
1929
1930static int adev_dump(const audio_hw_device_t *device, int fd)
1931{
1932 return 0;
1933}
1934
1935static int adev_close(hw_device_t *device)
1936{
1937 struct audio_device *adev = (struct audio_device *)device;
1938 audio_route_free(adev->audio_route);
1939 free(device);
1940 return 0;
1941}
1942
1943static void init_platform_data(struct audio_device *adev)
1944{
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -08001945 char platform[PROPERTY_VALUE_MAX];
1946 char baseband[PROPERTY_VALUE_MAX];
1947 char value[PROPERTY_VALUE_MAX];
1948 int mccmnc;
1949
1950 adev->dualmic_config = DUALMIC_CONFIG_NONE;
1951 adev->fluence_in_voice_call = false;
1952 adev->fluence_in_voice_rec = false;
1953 adev->mic_type_analog = false;
1954
1955 property_get("persist.audio.handset.mic.type",value,"");
1956 if (!strncmp("analog", value, 6))
1957 adev->mic_type_analog = true;
1958
1959 property_get("persist.audio.dualmic.config",value,"");
1960 if (!strncmp("broadside", value, 9)) {
1961 adev->dualmic_config = DUALMIC_CONFIG_BROADSIDE;
1962 adev->acdb_settings |= DMIC_FLAG;
1963 } else if (!strncmp("endfire", value, 7)) {
1964 adev->dualmic_config = DUALMIC_CONFIG_ENDFIRE;
1965 adev->acdb_settings |= DMIC_FLAG;
1966 }
1967
1968 if (adev->dualmic_config != DUALMIC_CONFIG_NONE) {
1969 property_get("persist.audio.fluence.voicecall",value,"");
1970 if (!strncmp("true", value, 4)) {
1971 adev->fluence_in_voice_call = true;
1972 }
1973
1974 property_get("persist.audio.fluence.voicerec",value,"");
1975 if (!strncmp("true", value, 4)) {
1976 adev->fluence_in_voice_rec = true;
1977 }
1978 }
1979
1980 property_get("gsm.sim.operator.numeric",value,"0");
1981 mccmnc = atoi(value);
1982 ALOGV("%s: tmus mccmnc %d", __func__, mccmnc);
1983 switch(mccmnc) {
1984 /* TMUS MCC(310), MNC(490, 260, 026) */
1985 case 310490:
1986 case 310260:
1987 case 310026:
1988 adev->is_tmus = true;
1989 break;
1990 default:
1991 adev->is_tmus = false;
1992 break;
1993 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001994
1995 adev->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
1996 if (adev->acdb_handle == NULL) {
1997 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_ACDB_LOADER);
1998 } else {
1999 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_ACDB_LOADER);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002000 adev->acdb_deallocate = (acdb_deallocate_t)dlsym(adev->acdb_handle,
2001 "acdb_loader_deallocate_ACDB");
2002 adev->acdb_send_audio_cal = (acdb_send_audio_cal_t)dlsym(adev->acdb_handle,
2003 "acdb_loader_send_audio_cal");
2004 adev->acdb_send_voice_cal = (acdb_send_voice_cal_t)dlsym(adev->acdb_handle,
2005 "acdb_loader_send_voice_cal");
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002006 adev->acdb_init = (acdb_init_t)dlsym(adev->acdb_handle,
2007 "acdb_loader_init_ACDB");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002008 if (adev->acdb_init == NULL)
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002009 ALOGE("%s: dlsym error %s for acdb_loader_init_ACDB", __func__, dlerror());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002010 else
2011 adev->acdb_init();
2012 }
2013
2014 /* If platform is Fusion3, load CSD Client specific symbols
2015 * Voice call is handled by MDM and apps processor talks to
2016 * MDM through CSD Client
2017 */
2018 property_get("ro.board.platform", platform, "");
2019 property_get("ro.baseband", baseband, "");
2020 if (!strcmp("msm8960", platform) && !strcmp("mdm", baseband)) {
2021 adev->csd_client = dlopen(LIB_CSD_CLIENT, RTLD_NOW);
2022 if (adev->csd_client == NULL)
2023 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_CSD_CLIENT);
2024 }
2025
2026 if (adev->csd_client) {
2027 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_CSD_CLIENT);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002028 adev->csd_client_deinit = (csd_client_deinit_t)dlsym(adev->csd_client,
2029 "csd_client_deinit");
2030 adev->csd_disable_device = (csd_disable_device_t)dlsym(adev->csd_client,
2031 "csd_client_disable_device");
2032 adev->csd_enable_device = (csd_enable_device_t)dlsym(adev->csd_client,
2033 "csd_client_enable_device");
2034 adev->csd_start_voice = (csd_start_voice_t)dlsym(adev->csd_client,
2035 "csd_client_start_voice");
2036 adev->csd_stop_voice = (csd_stop_voice_t)dlsym(adev->csd_client,
2037 "csd_client_stop_voice");
2038 adev->csd_volume = (csd_volume_t)dlsym(adev->csd_client,
2039 "csd_client_volume");
2040 adev->csd_mic_mute = (csd_mic_mute_t)dlsym(adev->csd_client,
2041 "csd_client_mic_mute");
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002042 adev->csd_client_init = (csd_client_init_t)dlsym(adev->csd_client,
2043 "csd_client_init");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002044
2045 if (adev->csd_client_init == NULL) {
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002046 ALOGE("%s: dlsym error %s for csd_client_init", __func__, dlerror());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002047 } else {
2048 adev->csd_client_init();
2049 }
2050 }
2051}
2052
2053static int adev_open(const hw_module_t *module, const char *name,
2054 hw_device_t **device)
2055{
2056 struct audio_device *adev;
2057 int ret;
2058
2059 ALOGV("%s: enter", __func__);
2060 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
2061
2062 adev = calloc(1, sizeof(struct audio_device));
2063
2064 adev->mixer = mixer_open(MIXER_CARD);
2065 if (!adev->mixer) {
2066 ALOGE("Unable to open the mixer, aborting.");
2067 return -ENOSYS;
2068 }
2069
2070 adev->audio_route = audio_route_init(MIXER_CARD, MIXER_XML_PATH);
2071 if (!adev->audio_route) {
2072 free(adev);
2073 ALOGE("%s: Failed to init audio route controls, aborting.", __func__);
2074 *device = NULL;
2075 return -EINVAL;
2076 }
2077
2078 adev->device.common.tag = HARDWARE_DEVICE_TAG;
2079 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
2080 adev->device.common.module = (struct hw_module_t *)module;
2081 adev->device.common.close = adev_close;
2082
2083 adev->device.init_check = adev_init_check;
2084 adev->device.set_voice_volume = adev_set_voice_volume;
2085 adev->device.set_master_volume = adev_set_master_volume;
2086 adev->device.get_master_volume = adev_get_master_volume;
2087 adev->device.set_master_mute = adev_set_master_mute;
2088 adev->device.get_master_mute = adev_get_master_mute;
2089 adev->device.set_mode = adev_set_mode;
2090 adev->device.set_mic_mute = adev_set_mic_mute;
2091 adev->device.get_mic_mute = adev_get_mic_mute;
2092 adev->device.set_parameters = adev_set_parameters;
2093 adev->device.get_parameters = adev_get_parameters;
2094 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
2095 adev->device.open_output_stream = adev_open_output_stream;
2096 adev->device.close_output_stream = adev_close_output_stream;
2097 adev->device.open_input_stream = adev_open_input_stream;
2098 adev->device.close_input_stream = adev_close_input_stream;
2099 adev->device.dump = adev_dump;
2100
2101 /* Set the default route before the PCM stream is opened */
2102 pthread_mutex_lock(&adev->lock);
2103 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08002104 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002105 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002106 adev->voice_call_rx = NULL;
2107 adev->voice_call_tx = NULL;
2108 adev->voice_volume = 1.0f;
2109 adev->tty_mode = TTY_MODE_OFF;
2110 adev->bluetooth_nrec = true;
2111 adev->cur_out_snd_device = 0;
2112 adev->cur_in_snd_device = 0;
2113 adev->out_snd_device_active = false;
2114 adev->in_snd_device_active = false;
2115 adev->usecase_list.next = NULL;
2116 adev->usecase_list.id = USECASE_INVALID;
2117 adev->in_call = false;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08002118 adev->acdb_settings = TTY_MODE_OFF;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002119 pthread_mutex_unlock(&adev->lock);
2120
2121 /* Loads platform specific libraries dynamically */
2122 init_platform_data(adev);
2123
2124 *device = &adev->device.common;
2125
2126 ALOGV("%s: exit", __func__);
2127 return 0;
2128}
2129
2130static struct hw_module_methods_t hal_module_methods = {
2131 .open = adev_open,
2132};
2133
2134struct audio_module HAL_MODULE_INFO_SYM = {
2135 .common = {
2136 .tag = HARDWARE_MODULE_TAG,
2137 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
2138 .hal_api_version = HARDWARE_HAL_API_VERSION,
2139 .id = AUDIO_HARDWARE_MODULE_ID,
2140 .name = "QCOM Audio HAL",
2141 .author = "Code Aurora Forum",
2142 .methods = &hal_module_methods,
2143 },
2144};