blob: 9b3ec13a8308be49b1579faf90d7a4fa943b9366 [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*/
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080019#define LOG_NDDEBUG 0
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080020
21#include <errno.h>
22#include <pthread.h>
23#include <stdint.h>
24#include <sys/time.h>
25#include <stdlib.h>
26#include <dlfcn.h>
27#include <math.h>
28
29#include <cutils/log.h>
30#include <cutils/str_parms.h>
31#include <cutils/properties.h>
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080032#include <cutils/list.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080033
34#include "audio_hw.h"
35
36#define LIB_ACDB_LOADER "/system/lib/libacdbloader.so"
37#define LIB_CSD_CLIENT "/system/lib/libcsd-client.so"
38#define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
39#define MIXER_CARD 0
40
41#define STRING_TO_ENUM(string) { #string, string }
42
43/* Flags used to initialize acdb_settings variable that goes to ACDB library */
44#define DMIC_FLAG 0x00000002
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080045#define TTY_MODE_OFF 0x00000010
46#define TTY_MODE_FULL 0x00000020
47#define TTY_MODE_VCO 0x00000040
48#define TTY_MODE_HCO 0x00000080
49#define TTY_MODE_CLEAR 0xFFFFFF0F
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080050
51struct string_to_enum {
52 const char *name;
53 uint32_t value;
54};
55
56static const struct string_to_enum out_channels_name_to_enum_table[] = {
57 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
58 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
59 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
60};
61
62static const char * const use_case_table[AUDIO_USECASE_MAX] = {
63 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
64 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
65 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
66 [USECASE_AUDIO_RECORD] = "audio-record",
67 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
68 [USECASE_VOICE_CALL] = "voice-call",
69};
70
71static const int pcm_device_table[AUDIO_USECASE_MAX][2] = {
72 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
Sungmin Choi5195a4b2013-04-03 21:54:22 -070073#ifdef MSM8974
74 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
75#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080076 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {14, 14},
Sungmin Choi5195a4b2013-04-03 21:54:22 -070077#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080078 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
79 [USECASE_AUDIO_RECORD] = {0, 0},
80 [USECASE_AUDIO_RECORD_LOW_LATENCY] = {14, 14},
Shashank Mittald2f3c3b2013-05-02 20:27:47 -070081#ifdef MSM8974
82 [USECASE_VOICE_CALL] = {2, 2},
83#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080084 [USECASE_VOICE_CALL] = {12, 12},
Shashank Mittald2f3c3b2013-05-02 20:27:47 -070085#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080086};
87
88/* Array to store sound devices */
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080089static const char * const device_table[SND_DEVICE_MAX] = {
90 [SND_DEVICE_NONE] = "none",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080091 /* Playback sound devices */
92 [SND_DEVICE_OUT_HANDSET] = "handset",
93 [SND_DEVICE_OUT_SPEAKER] = "speaker",
94 [SND_DEVICE_OUT_HEADPHONES] = "headphones",
95 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones",
Ravi Kumar Alamanda87f6ee02013-05-07 14:20:11 -070096 [SND_DEVICE_OUT_VOICE_HANDSET] = "voice-handset",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080097 [SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker",
98 [SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones",
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -080099 [SND_DEVICE_OUT_HDMI] = "hdmi",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800100 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
101 [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800102 [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = "voice-handset-tmus",
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800103 [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = "voice-tty-full-headphones",
104 [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = "voice-tty-vco-headphones",
105 [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = "voice-tty-hco-handset",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800106
107 /* Capture sound devices */
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800108 [SND_DEVICE_IN_HANDSET_MIC] = "handset-mic",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800109 [SND_DEVICE_IN_SPEAKER_MIC] = "speaker-mic",
110 [SND_DEVICE_IN_HEADSET_MIC] = "headset-mic",
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -0700111 [SND_DEVICE_IN_HANDSET_MIC_AEC] = "handset-mic",
112 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = "voice-speaker-mic",
113 [SND_DEVICE_IN_HEADSET_MIC_AEC] = "headset-mic",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800114 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "voice-speaker-mic",
115 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "voice-headset-mic",
116 [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic",
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800117 [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800118 [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic",
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800119 [SND_DEVICE_IN_VOICE_DMIC_EF] = "voice-dmic-ef",
120 [SND_DEVICE_IN_VOICE_DMIC_BS] = "voice-dmic-bs",
121 [SND_DEVICE_IN_VOICE_DMIC_EF_TMUS] = "voice-dmic-ef-tmus",
122 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF] = "voice-speaker-dmic-ef",
123 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS] = "voice-speaker-dmic-bs",
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800124 [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = "voice-tty-full-headset-mic",
125 [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = "voice-tty-vco-handset-mic",
126 [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = "voice-tty-hco-headset-mic",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800127 [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic",
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800128 [SND_DEVICE_IN_VOICE_REC_DMIC_EF] = "voice-rec-dmic-ef",
129 [SND_DEVICE_IN_VOICE_REC_DMIC_BS] = "voice-rec-dmic-bs",
Eric Laurentc8400632013-02-14 19:04:54 -0800130 [SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE] = "voice-rec-dmic-ef-fluence",
131 [SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE] = "voice-rec-dmic-bs-fluence",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800132};
133
Eric Laurentc8400632013-02-14 19:04:54 -0800134/* ACDB IDs (audio DSP path configuration IDs) for each sound device */
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800135static const int acdb_device_table[SND_DEVICE_MAX] = {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700136 [SND_DEVICE_NONE] = -1,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800137 [SND_DEVICE_OUT_HANDSET] = 7,
Ravi Kumar Alamanda87f6ee02013-05-07 14:20:11 -0700138#ifdef MSM8974
139 [SND_DEVICE_OUT_SPEAKER] = 15,
140#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800141 [SND_DEVICE_OUT_SPEAKER] = 14,
Ravi Kumar Alamanda87f6ee02013-05-07 14:20:11 -0700142#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800143 [SND_DEVICE_OUT_HEADPHONES] = 10,
144 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = 10,
Ravi Kumar Alamanda87f6ee02013-05-07 14:20:11 -0700145 [SND_DEVICE_OUT_VOICE_HANDSET] = 7,
146#ifdef MSM8974
147 [SND_DEVICE_OUT_VOICE_SPEAKER] = 15,
148#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800149 [SND_DEVICE_OUT_VOICE_SPEAKER] = 14,
Ravi Kumar Alamanda87f6ee02013-05-07 14:20:11 -0700150#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800151 [SND_DEVICE_OUT_VOICE_HEADPHONES] = 10,
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800152 [SND_DEVICE_OUT_HDMI] = 18,
Ravi Kumar Alamanda87f6ee02013-05-07 14:20:11 -0700153#ifdef MSM8974
154 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 15,
155#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800156 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 14,
Ravi Kumar Alamanda87f6ee02013-05-07 14:20:11 -0700157#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800158 [SND_DEVICE_OUT_BT_SCO] = 22,
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800159 [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = 81,
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800160 [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = 17,
161 [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = 17,
162 [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = 37,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800163
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800164 [SND_DEVICE_IN_HANDSET_MIC] = 4,
Ravi Kumar Alamanda87f6ee02013-05-07 14:20:11 -0700165 [SND_DEVICE_IN_SPEAKER_MIC] = 4, /* ToDo: Check if this needs to changed to 11 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800166 [SND_DEVICE_IN_HEADSET_MIC] = 8,
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -0700167 [SND_DEVICE_IN_HANDSET_MIC_AEC] = 40,
168 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = 42,
169 [SND_DEVICE_IN_HEADSET_MIC_AEC] = 47,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800170 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = 11,
171 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = 8,
172 [SND_DEVICE_IN_HDMI_MIC] = 4,
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800173 [SND_DEVICE_IN_BT_SCO_MIC] = 21,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800174 [SND_DEVICE_IN_CAMCORDER_MIC] = 61,
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800175 [SND_DEVICE_IN_VOICE_DMIC_EF] = 6,
176 [SND_DEVICE_IN_VOICE_DMIC_BS] = 5,
177 [SND_DEVICE_IN_VOICE_DMIC_EF_TMUS] = 91,
178 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF] = 13,
179 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS] = 12,
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800180 [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = 16,
181 [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = 36,
182 [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = 16,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800183 [SND_DEVICE_IN_VOICE_REC_MIC] = 62,
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -0700184 /* TODO: Update with proper acdb ids */
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800185 [SND_DEVICE_IN_VOICE_REC_DMIC_EF] = 62,
186 [SND_DEVICE_IN_VOICE_REC_DMIC_BS] = 62,
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -0700187 [SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE] = 6,
188 [SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE] = 5,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800189};
190
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800191int edid_get_max_channels(void);
192
Ravi Kumar Alamanda37718842013-02-22 18:44:45 -0800193static pthread_once_t check_op_once_ctl = PTHREAD_ONCE_INIT;
194static bool is_tmus = false;
195
196static void check_operator()
197{
198 char value[PROPERTY_VALUE_MAX];
199 int mccmnc;
200 property_get("gsm.sim.operator.numeric",value,"0");
201 mccmnc = atoi(value);
202 ALOGD("%s: tmus mccmnc %d", __func__, mccmnc);
203 switch(mccmnc) {
204 /* TMUS MCC(310), MNC(490, 260, 026) */
205 case 310490:
206 case 310260:
207 case 310026:
208 is_tmus = true;
209 break;
210 }
211}
212
213static bool is_operator_tmus()
214{
215 pthread_once(&check_op_once_ctl, check_operator);
216 return is_tmus;
217}
218
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800219static int get_pcm_device_id(struct audio_route *ar,
220 audio_usecase_t usecase,
221 int device_type)
222{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800223 int device_id;
224 if (device_type == PCM_PLAYBACK)
225 device_id = pcm_device_table[usecase][0];
226 else
227 device_id = pcm_device_table[usecase][1];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800228 return device_id;
229}
230
231static int get_acdb_device_id(snd_device_t snd_device)
232{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700233 return acdb_device_table[snd_device];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800234}
235
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800236static void add_backend_name(char *mixer_path,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700237 snd_device_t snd_device)
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800238{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700239 if (snd_device == SND_DEVICE_IN_BT_SCO_MIC)
240 strcat(mixer_path, " bt-sco");
241 else if(snd_device == SND_DEVICE_OUT_BT_SCO)
242 strcat(mixer_path, " bt-sco");
243 else if (snd_device == SND_DEVICE_OUT_HDMI)
244 strcat(mixer_path, " hdmi");
245 else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HDMI)
246 strcat(mixer_path, " speaker-and-hdmi");
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800247}
248
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700249static int enable_audio_route(struct audio_device *adev,
250 struct audio_usecase *usecase,
251 bool update_mixer)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800252{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700253 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800254 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800255
256 if (usecase == NULL)
257 return -EINVAL;
258
259 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
260
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800261 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700262 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800263 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700264 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800265
266 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700267 add_backend_name(mixer_path, snd_device);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800268 ALOGD("%s: apply mixer path: %s", __func__, mixer_path);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700269 audio_route_apply_path(adev->audio_route, mixer_path);
270 if (update_mixer)
271 audio_route_update_mixer(adev->audio_route);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800272
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800273 ALOGV("%s: exit", __func__);
274 return 0;
275}
276
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700277static int disable_audio_route(struct audio_device *adev,
278 struct audio_usecase *usecase,
279 bool update_mixer)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800280{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700281 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800282 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800283
284 if (usecase == NULL)
285 return -EINVAL;
286
287 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700288 if (usecase->type == PCM_CAPTURE)
289 snd_device = usecase->in_snd_device;
290 else
291 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800292 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700293 add_backend_name(mixer_path, snd_device);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800294 ALOGD("%s: reset mixer path: %s", __func__, mixer_path);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700295 audio_route_reset_path(adev->audio_route, mixer_path);
296 if (update_mixer)
297 audio_route_update_mixer(adev->audio_route);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800299 ALOGV("%s: exit", __func__);
300 return 0;
301}
302
303static int enable_snd_device(struct audio_device *adev,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700304 snd_device_t snd_device,
305 bool update_mixer)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800306{
307 int acdb_dev_id, acdb_dev_type;
308
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800309 if (snd_device < SND_DEVICE_MIN ||
310 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800311 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800312 return -EINVAL;
313 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700314
315 adev->snd_dev_ref_cnt[snd_device]++;
316 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
317 ALOGD("%s: snd_device(%d: %s) is already active",
318 __func__, snd_device, device_table[snd_device]);
319 return 0;
320 }
321
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800322 acdb_dev_id = get_acdb_device_id(snd_device);
323 if (acdb_dev_id < 0) {
324 ALOGE("%s: Could not find acdb id for device(%d)",
325 __func__, snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700326 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800327 return -EINVAL;
328 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800329 if (adev->acdb_send_audio_cal) {
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -0700330 ALOGD("%s: sending audio calibration for snd_device(%d) acdb_id(%d)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800331 __func__, snd_device, acdb_dev_id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700332 if (snd_device >= SND_DEVICE_OUT_BEGIN &&
333 snd_device < SND_DEVICE_OUT_END)
334 acdb_dev_type = ACDB_DEV_TYPE_OUT;
335 else
336 acdb_dev_type = ACDB_DEV_TYPE_IN;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800337 adev->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type);
338 } else {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700339 ALOGW("%s: Could not find the symbol acdb_send_audio_cal from %s",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800340 __func__, LIB_ACDB_LOADER);
341 }
342
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700343 ALOGD("%s: snd_device(%d: %s)", __func__,
344 snd_device, device_table[snd_device]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800345 audio_route_apply_path(adev->audio_route, device_table[snd_device]);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700346 if (update_mixer)
347 audio_route_update_mixer(adev->audio_route);
348
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800349 return 0;
350}
351
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700352static int disable_snd_device(struct audio_device *adev,
353 snd_device_t snd_device,
354 bool update_mixer)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800355{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800356 if (snd_device < SND_DEVICE_MIN ||
357 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800358 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800359 return -EINVAL;
360 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700361 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
362 ALOGE("%s: device ref cnt is already 0", __func__);
363 return -EINVAL;
364 }
365 adev->snd_dev_ref_cnt[snd_device]--;
366 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
367 ALOGD("%s: snd_device(%d: %s)", __func__,
368 snd_device, device_table[snd_device]);
369 audio_route_reset_path(adev->audio_route, device_table[snd_device]);
370 if (update_mixer)
371 audio_route_update_mixer(adev->audio_route);
372 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800373 return 0;
374}
375
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700376static void check_usecases_codec_backend(struct audio_device *adev,
377 struct audio_usecase *uc_info,
378 snd_device_t snd_device)
379{
380 struct listnode *node;
381 struct audio_usecase *usecase;
382 bool switch_device[AUDIO_USECASE_MAX];
383 int i, num_uc_to_switch = 0;
384
385 /*
386 * This function is to make sure that all the usecases that are active on
387 * the hardware codec backend are always routed to any one device that is
388 * handled by the hardware codec.
389 * For example, if low-latency and deep-buffer usecases are currently active
390 * on speaker and out_set_parameters(headset) is received on low-latency
391 * output, then we have to make sure deep-buffer is also switched to headset,
392 * because of the limitation that both the devices cannot be enabled
393 * at the same time as they share the same backend.
394 */
395 /* Disable all the usecases on the shared backend other than the
396 specified usecase */
397 for (i = 0; i < AUDIO_USECASE_MAX; i++)
398 switch_device[i] = false;
399
400 list_for_each(node, &adev->usecase_list) {
401 usecase = node_to_item(node, struct audio_usecase, list);
402 if (usecase->type != PCM_CAPTURE &&
403 usecase != uc_info &&
404 usecase->out_snd_device != snd_device &&
405 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
406 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
407 __func__, use_case_table[usecase->id],
408 device_table[usecase->out_snd_device]);
409 disable_audio_route(adev, usecase, false);
410 switch_device[usecase->id] = true;
411 num_uc_to_switch++;
412 }
413 }
414
415 if (num_uc_to_switch) {
416 /* Make sure all the streams are de-routed before disabling the device */
417 audio_route_update_mixer(adev->audio_route);
418
419 list_for_each(node, &adev->usecase_list) {
420 usecase = node_to_item(node, struct audio_usecase, list);
421 if (switch_device[usecase->id]) {
422 disable_snd_device(adev, usecase->out_snd_device, false);
423 enable_snd_device(adev, snd_device, false);
424 }
425 }
426
427 /* Make sure new snd device is enabled before re-routing the streams */
428 audio_route_update_mixer(adev->audio_route);
429
430 /* Re-route all the usecases on the shared backend other than the
431 specified usecase to new snd devices */
432 list_for_each(node, &adev->usecase_list) {
433 usecase = node_to_item(node, struct audio_usecase, list);
434 /* Update the out_snd_device only before enabling the audio route */
435 if (switch_device[usecase->id] ) {
436 usecase->out_snd_device = snd_device;
437 enable_audio_route(adev, usecase, false);
438 }
439 }
440
441 audio_route_update_mixer(adev->audio_route);
442 }
443}
444
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -0700445static int set_echo_reference(struct mixer *mixer, const char* ec_ref)
446{
447 struct mixer_ctl *ctl;
448 const char *mixer_ctl_name = "EC_REF_RX";
449
450 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
451 if (!ctl) {
452 ALOGE("%s: Could not get ctl for mixer cmd - %s",
453 __func__, mixer_ctl_name);
454 return -EINVAL;
455 }
456 ALOGV("Setting EC Reference: %s", ec_ref);
457 mixer_ctl_set_enum_by_string(ctl, ec_ref);
458 return 0;
459}
460
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800461static int set_hdmi_channels(struct mixer *mixer,
462 int channel_count)
463{
464 struct mixer_ctl *ctl;
465 const char *channel_cnt_str = NULL;
466 const char *mixer_ctl_name = "HDMI_RX Channels";
467 switch (channel_count) {
468 case 8:
469 channel_cnt_str = "Eight"; break;
470 case 7:
471 channel_cnt_str = "Seven"; break;
472 case 6:
473 channel_cnt_str = "Six"; break;
474 case 5:
475 channel_cnt_str = "Five"; break;
476 case 4:
477 channel_cnt_str = "Four"; break;
478 case 3:
479 channel_cnt_str = "Three"; break;
480 default:
481 channel_cnt_str = "Two"; break;
482 }
483 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
484 if (!ctl) {
485 ALOGE("%s: Could not get ctl for mixer cmd - %s",
486 __func__, mixer_ctl_name);
487 return -EINVAL;
488 }
489 ALOGV("HDMI channel count: %s", channel_cnt_str);
490 mixer_ctl_set_enum_by_string(ctl, channel_cnt_str);
491 return 0;
492}
493
494/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700495static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800496{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700497 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800498 int channels = edid_get_max_channels();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800499
500 switch (channels) {
501 /*
502 * Do not handle stereo output in Multi-channel cases
503 * Stereo case is handled in normal playback path
504 */
505 case 6:
506 ALOGV("%s: HDMI supports 5.1", __func__);
507 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
508 break;
509 case 8:
510 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
511 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
512 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
513 break;
514 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700515 ALOGE("HDMI does not support multi channel playback");
516 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800517 break;
518 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700519 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800520}
521
Ravi Kumar Alamanda87f6ee02013-05-07 14:20:11 -0700522static int set_voice_volume(struct mixer *mixer,
523 int volume)
524{
525 struct mixer_ctl *ctl;
526 const char *mixer_ctl_name = "Voice Rx Volume";
527 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
528 if (!ctl) {
529 ALOGE("%s: Could not get ctl for mixer cmd - %s",
530 __func__, mixer_ctl_name);
531 return -EINVAL;
532 }
533 ALOGV("Setting voice volume: %d", volume);
534 mixer_ctl_set_value(ctl, 0, volume);
535 return 0;
536}
537
538static int set_mic_mute(struct mixer *mixer,
539 int mute)
540{
541 struct mixer_ctl *ctl;
542 const char *mixer_ctl_name = "Voice Tx Mute";
543 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
544 if (!ctl) {
545 ALOGE("%s: Could not get ctl for mixer cmd - %s",
546 __func__, mixer_ctl_name);
547 return -EINVAL;
548 }
549 ALOGV("Setting mic mute: %d", mute);
550 mixer_ctl_set_value(ctl, 0, mute);
551 return 0;
552}
553
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700554static snd_device_t get_output_snd_device(struct audio_device *adev,
555 audio_devices_t devices)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800556{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700557 audio_mode_t mode = adev->mode;
558 snd_device_t snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800559
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800560 ALOGV("%s: enter: output devices(%#x)", __func__, devices);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800561 if (devices == AUDIO_DEVICE_NONE ||
562 devices & AUDIO_DEVICE_BIT_IN) {
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800563 ALOGV("%s: Invalid output devices (%#x)", __func__, devices);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800564 goto exit;
565 }
566
567 if (mode == AUDIO_MODE_IN_CALL) {
568 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
569 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800570 if (adev->tty_mode == TTY_MODE_FULL)
571 snd_device = SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES;
572 else if (adev->tty_mode == TTY_MODE_VCO)
573 snd_device = SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES;
574 else if (adev->tty_mode == TTY_MODE_HCO)
575 snd_device = SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET;
576 else
577 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800578 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
579 snd_device = SND_DEVICE_OUT_BT_SCO;
580 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
581 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
582 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
Ravi Kumar Alamanda37718842013-02-22 18:44:45 -0800583 if (is_operator_tmus())
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800584 snd_device = SND_DEVICE_OUT_VOICE_HANDSET_TMUS;
585 else
586 snd_device = SND_DEVICE_OUT_HANDSET;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800587 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800588 if (snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800589 goto exit;
590 }
591 }
592
593 if (popcount(devices) == 2) {
594 if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
595 AUDIO_DEVICE_OUT_SPEAKER)) {
596 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
597 } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
598 AUDIO_DEVICE_OUT_SPEAKER)) {
599 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
600 } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL |
601 AUDIO_DEVICE_OUT_SPEAKER)) {
602 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
603 } else {
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800604 ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800605 goto exit;
606 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800607 if (snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800608 goto exit;
609 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800610 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800611
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800612 if (popcount(devices) != 1) {
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800613 ALOGE("%s: Invalid output devices(%#x)", __func__, devices);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800614 goto exit;
615 }
616
617 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
618 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
619 snd_device = SND_DEVICE_OUT_HEADPHONES;
620 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
621 snd_device = SND_DEVICE_OUT_SPEAKER;
622 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
623 snd_device = SND_DEVICE_OUT_BT_SCO;
624 } else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
625 snd_device = SND_DEVICE_OUT_HDMI ;
626 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
627 snd_device = SND_DEVICE_OUT_HANDSET;
628 } else {
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800629 ALOGE("%s: Unknown device(s) %#x", __func__, devices);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800630 }
631exit:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800632 ALOGV("%s: exit: snd_device(%s)", __func__, device_table[snd_device]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800633 return snd_device;
634}
635
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700636static snd_device_t get_input_snd_device(struct audio_device *adev,
637 audio_devices_t out_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800638{
Eric Laurentc8400632013-02-14 19:04:54 -0800639 audio_source_t source = (adev->active_input == NULL) ?
640 AUDIO_SOURCE_DEFAULT : adev->active_input->source;
641
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800642 audio_mode_t mode = adev->mode;
Eric Laurentc8400632013-02-14 19:04:54 -0800643 audio_devices_t in_device = ((adev->active_input == NULL) ?
644 AUDIO_DEVICE_NONE : adev->active_input->device)
645 & ~AUDIO_DEVICE_BIT_IN;
646 audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
647 AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800648 snd_device_t snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800649
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800650 ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800651 __func__, out_device, in_device);
652 if (mode == AUDIO_MODE_IN_CALL) {
653 if (out_device == AUDIO_DEVICE_NONE) {
654 ALOGE("%s: No output device set for voice call", __func__);
655 goto exit;
656 }
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800657 if (adev->tty_mode != TTY_MODE_OFF) {
658 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
659 out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
660 switch (adev->tty_mode) {
661 case TTY_MODE_FULL:
662 snd_device = SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC;
663 break;
664 case TTY_MODE_VCO:
665 snd_device = SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC;
666 break;
667 case TTY_MODE_HCO:
668 snd_device = SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC;
669 break;
670 default:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800671 ALOGE("%s: Invalid TTY mode (%#x)", __func__, adev->tty_mode);
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800672 }
673 goto exit;
674 }
675 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800676 if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
677 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800678 if (adev->mic_type_analog || adev->fluence_in_voice_call == false) {
679 snd_device = SND_DEVICE_IN_HANDSET_MIC;
680 } else {
681 if (adev->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
Ravi Kumar Alamanda37718842013-02-22 18:44:45 -0800682 if (is_operator_tmus())
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800683 snd_device = SND_DEVICE_IN_VOICE_DMIC_EF_TMUS;
684 else
685 snd_device = SND_DEVICE_IN_VOICE_DMIC_EF;
686 } else if(adev->dualmic_config == DUALMIC_CONFIG_BROADSIDE)
687 snd_device = SND_DEVICE_IN_VOICE_DMIC_BS;
688 else
689 snd_device = SND_DEVICE_IN_HANDSET_MIC;
690 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800691 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
692 snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
693 } else if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
694 snd_device = SND_DEVICE_IN_BT_SCO_MIC ;
695 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
Ravi Kumar Alamanda02317792013-03-04 20:56:50 -0800696 if (adev->fluence_in_voice_call && adev->fluence_in_spkr_mode &&
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800697 adev->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
698 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF;
Ravi Kumar Alamanda02317792013-03-04 20:56:50 -0800699 } else if (adev->fluence_in_voice_call && adev->fluence_in_spkr_mode &&
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800700 adev->dualmic_config == DUALMIC_CONFIG_BROADSIDE) {
701 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS;
702 } else {
703 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
704 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800705 }
706 } else if (source == AUDIO_SOURCE_CAMCORDER) {
707 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
708 in_device & AUDIO_DEVICE_IN_BACK_MIC) {
709 snd_device = SND_DEVICE_IN_CAMCORDER_MIC;
710 }
711 } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) {
712 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
Eric Laurentc8400632013-02-14 19:04:54 -0800713 if (adev->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
714 if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
715 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_EF;
716 else if (adev->fluence_in_voice_rec)
717 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE;
Eric Laurentc8400632013-02-14 19:04:54 -0800718 } else if (adev->dualmic_config == DUALMIC_CONFIG_BROADSIDE) {
719 if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
720 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_BS;
721 else if (adev->fluence_in_voice_rec)
722 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -0700723 }
724
725 if (snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800726 snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -0700727 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800728 }
Ravi Kumar Alamanda8455fa72013-02-19 14:53:19 -0800729 } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
730 if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
731 in_device = AUDIO_DEVICE_IN_BACK_MIC;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -0700732 if (adev->active_input) {
733 if (adev->active_input->enable_aec) {
734 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
735 if (adev->mic_type_analog)
736 snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
737 else
738 snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
739 } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
740 snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
741 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
742 snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
743 }
744 set_echo_reference(adev->mixer, "SLIM_RX");
745 } else
746 set_echo_reference(adev->mixer, "NONE");
747 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800748 } else if (source == AUDIO_SOURCE_DEFAULT) {
749 goto exit;
750 }
751
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -0700752
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800753 if (snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800754 goto exit;
755 }
756
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800757 if (in_device != AUDIO_DEVICE_NONE &&
Ravi Kumar Alamanda8455fa72013-02-19 14:53:19 -0800758 !(in_device & AUDIO_DEVICE_IN_VOICE_CALL) &&
759 !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800760 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800761 snd_device = SND_DEVICE_IN_HANDSET_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800762 } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800763 if (adev->mic_type_analog)
764 snd_device = SND_DEVICE_IN_HANDSET_MIC;
765 else
766 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800767 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
768 snd_device = SND_DEVICE_IN_HEADSET_MIC;
769 } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
770 snd_device = SND_DEVICE_IN_BT_SCO_MIC ;
771 } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) {
772 snd_device = SND_DEVICE_IN_HDMI_MIC;
773 } else {
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800774 ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800775 ALOGW("%s: Using default handset-mic", __func__);
776 snd_device = SND_DEVICE_IN_HANDSET_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800777 }
778 } else {
779 if (out_device & AUDIO_DEVICE_OUT_EARPIECE) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800780 snd_device = SND_DEVICE_IN_HANDSET_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800781 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
782 snd_device = SND_DEVICE_IN_HEADSET_MIC;
783 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
784 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
785 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800786 snd_device = SND_DEVICE_IN_HANDSET_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800787 } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800788 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800789 } else if (out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
790 snd_device = SND_DEVICE_IN_HDMI_MIC;
791 } else {
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800792 ALOGE("%s: Unknown output device(s) %#x", __func__, out_device);
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800793 ALOGW("%s: Using default handset-mic", __func__);
794 snd_device = SND_DEVICE_IN_HANDSET_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800795 }
796 }
797exit:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800798 ALOGV("%s: exit: in_snd_device(%s)", __func__, device_table[snd_device]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800799 return snd_device;
800}
801
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700802static struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
803 audio_usecase_t uc_id)
804{
805 struct audio_usecase *usecase;
806 struct listnode *node;
807
808 list_for_each(node, &adev->usecase_list) {
809 usecase = node_to_item(node, struct audio_usecase, list);
810 if (usecase->id == uc_id)
811 return usecase;
812 }
813 return NULL;
814}
815
816static int select_devices(struct audio_device *adev,
817 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800818{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800819 snd_device_t out_snd_device = SND_DEVICE_NONE;
820 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700821 struct audio_usecase *usecase = NULL;
822 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800823 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800824 int acdb_rx_id, acdb_tx_id;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700825 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800826
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700827 usecase = get_usecase_from_list(adev, uc_id);
828 if (usecase == NULL) {
829 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
830 return -EINVAL;
831 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800832
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700833 if (usecase->type == VOICE_CALL) {
834 out_snd_device = get_output_snd_device(adev, usecase->stream.out->devices);
835 in_snd_device = get_input_snd_device(adev, usecase->stream.out->devices);
836 usecase->devices = usecase->stream.out->devices;
837 } else {
838 /*
839 * If the voice call is active, use the sound devices of voice call usecase
840 * so that it would not result any device switch. All the usecases will
841 * be switched to new device when select_devices() is called for voice call
842 * usecase. This is to avoid switching devices for voice call when
843 * check_usecases_codec_backend() is called below.
844 */
845 if (adev->in_call) {
846 vc_usecase = get_usecase_from_list(adev, USECASE_VOICE_CALL);
847 if (vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
848 in_snd_device = vc_usecase->in_snd_device;
849 out_snd_device = vc_usecase->out_snd_device;
850 }
851 }
852 if (usecase->type == PCM_PLAYBACK) {
853 usecase->devices = usecase->stream.out->devices;
854 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700855 if (out_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700856 out_snd_device = get_output_snd_device(adev,
857 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700858 if (usecase->stream.out == adev->primary_output &&
859 adev->active_input &&
860 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
861 select_devices(adev, adev->active_input->usecase);
862 }
863 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700864 } else if (usecase->type == PCM_CAPTURE) {
865 usecase->devices = usecase->stream.in->device;
866 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700867 if (in_snd_device == SND_DEVICE_NONE) {
868 if (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
869 adev->primary_output && !adev->primary_output->standby) {
870 in_snd_device = get_input_snd_device(adev,
871 adev->primary_output->devices);
872 } else {
873 in_snd_device = get_input_snd_device(adev, AUDIO_DEVICE_NONE);
874 }
875 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700876 }
877 }
878
879 if (out_snd_device == usecase->out_snd_device &&
880 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800881 return 0;
882 }
883
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800884 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
885 out_snd_device, device_table[out_snd_device],
886 in_snd_device, device_table[in_snd_device]);
887
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800888 /*
889 * Limitation: While in call, to do a device switch we need to disable
890 * and enable both RX and TX devices though one of them is same as current
891 * device.
892 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700893 if (usecase->type == VOICE_CALL && adev->csd_client != NULL &&
894 usecase->in_snd_device != SND_DEVICE_NONE &&
895 usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800896 /* This must be called before disabling the mixer controls on APQ side */
897 if (adev->csd_disable_device == NULL) {
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -0800898 ALOGE("%s: dlsym error for csd_client_disable_device", __func__);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800899 } else {
900 status = adev->csd_disable_device();
901 if (status < 0) {
902 ALOGE("%s: csd_client_disable_device, failed, error %d",
903 __func__, status);
904 }
905 }
906 }
907
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700908 /* Disable current sound devices */
909 if (usecase->out_snd_device != SND_DEVICE_NONE) {
910 disable_audio_route(adev, usecase, true);
911 disable_snd_device(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800912 }
913
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700914 if (usecase->in_snd_device != SND_DEVICE_NONE) {
915 disable_audio_route(adev, usecase, true);
916 disable_snd_device(adev, usecase->in_snd_device, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800917 }
918
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700919 /* Enable new sound devices */
920 if (out_snd_device != SND_DEVICE_NONE) {
921 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
922 check_usecases_codec_backend(adev, usecase, out_snd_device);
923 enable_snd_device(adev, out_snd_device, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800924 }
925
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700926 if (in_snd_device != SND_DEVICE_NONE)
927 enable_snd_device(adev, in_snd_device, false);
928
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800929 audio_route_update_mixer(adev->audio_route);
930
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700931 usecase->in_snd_device = in_snd_device;
932 usecase->out_snd_device = out_snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800933
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700934 enable_audio_route(adev, usecase, true);
935
936 if (usecase->type == VOICE_CALL && adev->csd_client) {
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800937 if (adev->csd_enable_device == NULL) {
938 ALOGE("%s: dlsym error for csd_client_enable_device",
939 __func__);
940 } else {
941 acdb_rx_id = get_acdb_device_id(out_snd_device);
942 acdb_tx_id = get_acdb_device_id(in_snd_device);
943
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700944 if (acdb_rx_id > 0 || acdb_tx_id > 0) {
945 status = adev->csd_enable_device(acdb_rx_id, acdb_tx_id,
946 adev->acdb_settings);
947 if (status < 0) {
948 ALOGE("%s: csd_client_enable_device, failed, error %d",
949 __func__, status);
950 }
951 } else {
952 ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__,
953 acdb_rx_id, acdb_tx_id);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800954 }
955 }
956 }
957
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800958 return status;
959}
960
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800961static int stop_input_stream(struct stream_in *in)
962{
963 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800964 struct audio_usecase *uc_info;
965 struct audio_device *adev = in->dev;
966
Eric Laurentc8400632013-02-14 19:04:54 -0800967 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800968
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700969 ALOGD("%s: enter: usecase(%d: %s)", __func__,
970 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800971 uc_info = get_usecase_from_list(adev, in->usecase);
972 if (uc_info == NULL) {
973 ALOGE("%s: Could not find the usecase (%d) in the list",
974 __func__, in->usecase);
975 return -EINVAL;
976 }
977
Eric Laurent150dbfe2013-02-27 14:31:02 -0800978 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700979 disable_audio_route(adev, uc_info, true);
980
981 /* 2. Disable the tx device */
982 disable_snd_device(adev, uc_info->in_snd_device, true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800983
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800984 list_remove(&uc_info->list);
985 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800986
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800987 ALOGD("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800988 return ret;
989}
990
991int start_input_stream(struct stream_in *in)
992{
993 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -0800994 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800995 struct audio_usecase *uc_info;
996 struct audio_device *adev = in->dev;
997
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800998 ALOGD("%s: enter: usecase(%d)", __func__, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800999 in->pcm_device_id = get_pcm_device_id(adev->audio_route,
1000 in->usecase,
1001 PCM_CAPTURE);
1002 if (in->pcm_device_id < 0) {
1003 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1004 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001005 ret = -EINVAL;
1006 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001007 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001008
1009 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001010 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1011 uc_info->id = in->usecase;
1012 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001013 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001014 uc_info->devices = in->device;
1015 uc_info->in_snd_device = SND_DEVICE_NONE;
1016 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001017
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001018 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001019 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001020
Eric Laurentc8400632013-02-14 19:04:54 -08001021 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1022 __func__, SOUND_CARD, in->pcm_device_id, in->config.channels);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001023 in->pcm = pcm_open(SOUND_CARD, in->pcm_device_id,
1024 PCM_IN, &in->config);
1025 if (in->pcm && !pcm_is_ready(in->pcm)) {
1026 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1027 pcm_close(in->pcm);
1028 in->pcm = NULL;
Eric Laurentc8400632013-02-14 19:04:54 -08001029 ret = -EIO;
1030 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001031 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001032 ALOGD("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001033 return ret;
1034
1035error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001036 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001037
1038error_config:
1039 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001040 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001041
1042 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001043}
1044
1045static int stop_output_stream(struct stream_out *out)
1046{
1047 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001048 struct audio_usecase *uc_info;
1049 struct audio_device *adev = out->dev;
1050
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001051 ALOGD("%s: enter: usecase(%d: %s)", __func__,
1052 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001053 uc_info = get_usecase_from_list(adev, out->usecase);
1054 if (uc_info == NULL) {
1055 ALOGE("%s: Could not find the usecase (%d) in the list",
1056 __func__, out->usecase);
1057 return -EINVAL;
1058 }
1059
Eric Laurent150dbfe2013-02-27 14:31:02 -08001060 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001061 disable_audio_route(adev, uc_info, true);
1062
1063 /* 2. Disable the rx device */
1064 disable_snd_device(adev, uc_info->out_snd_device, true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001065
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001066 list_remove(&uc_info->list);
1067 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001068
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001069 ALOGD("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001070 return ret;
1071}
1072
1073int start_output_stream(struct stream_out *out)
1074{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001075 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001076 struct audio_usecase *uc_info;
1077 struct audio_device *adev = out->dev;
1078
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001079 ALOGD("%s: enter: usecase(%d: %s) devices(%#x)",
1080 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001081 out->pcm_device_id = get_pcm_device_id(adev->audio_route,
1082 out->usecase,
1083 PCM_PLAYBACK);
1084 if (out->pcm_device_id < 0) {
1085 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1086 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001087 ret = -EINVAL;
1088 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001089 }
1090
1091 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1092 uc_info->id = out->usecase;
1093 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001094 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001095 uc_info->devices = out->devices;
1096 uc_info->in_snd_device = SND_DEVICE_NONE;
1097 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001098
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001099 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001100
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001101 select_devices(adev, out->usecase);
1102
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001103 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d)",
1104 __func__, 0, out->pcm_device_id);
1105 out->pcm = pcm_open(SOUND_CARD, out->pcm_device_id,
1106 PCM_OUT, &out->config);
1107 if (out->pcm && !pcm_is_ready(out->pcm)) {
1108 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1109 pcm_close(out->pcm);
1110 out->pcm = NULL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001111 ret = -EIO;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001112 goto error_pcm_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001113 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001114 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001115 return 0;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001116error_pcm_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001117 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001118error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001119 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001120}
1121
1122static int stop_voice_call(struct audio_device *adev)
1123{
1124 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001125 struct audio_usecase *uc_info;
1126
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001127 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -08001128 adev->in_call = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001129 if (adev->csd_client) {
1130 if (adev->csd_stop_voice == NULL) {
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001131 ALOGE("dlsym error for csd_client_disable_device");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001132 } else {
1133 ret = adev->csd_stop_voice();
1134 if (ret < 0) {
1135 ALOGE("%s: csd_client error %d\n", __func__, ret);
1136 }
1137 }
1138 }
1139
1140 /* 1. Close the PCM devices */
1141 if (adev->voice_call_rx) {
1142 pcm_close(adev->voice_call_rx);
1143 adev->voice_call_rx = NULL;
1144 }
1145 if (adev->voice_call_tx) {
1146 pcm_close(adev->voice_call_tx);
1147 adev->voice_call_tx = NULL;
1148 }
1149
1150 uc_info = get_usecase_from_list(adev, USECASE_VOICE_CALL);
1151 if (uc_info == NULL) {
1152 ALOGE("%s: Could not find the usecase (%d) in the list",
1153 __func__, USECASE_VOICE_CALL);
1154 return -EINVAL;
1155 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001156
1157 /* 2. Get and set stream specific mixer controls */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001158 disable_audio_route(adev, uc_info, true);
1159
1160 /* 3. Disable the rx and tx devices */
1161 disable_snd_device(adev, uc_info->out_snd_device, false);
1162 disable_snd_device(adev, uc_info->in_snd_device, true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001163
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001164 list_remove(&uc_info->list);
1165 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001166
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001167 ALOGD("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001168 return ret;
1169}
1170
1171static int start_voice_call(struct audio_device *adev)
1172{
1173 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001174 struct audio_usecase *uc_info;
1175 int pcm_dev_rx_id, pcm_dev_tx_id;
1176
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001177 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001178
1179 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1180 uc_info->id = USECASE_VOICE_CALL;
1181 uc_info->type = VOICE_CALL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001182 uc_info->stream.out = adev->primary_output;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001183 uc_info->devices = adev->primary_output->devices;
1184 uc_info->in_snd_device = SND_DEVICE_NONE;
1185 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001186
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001187 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001188
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001189 select_devices(adev, USECASE_VOICE_CALL);
1190
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001191 pcm_dev_rx_id = get_pcm_device_id(adev->audio_route, uc_info->id,
1192 PCM_PLAYBACK);
1193 pcm_dev_tx_id = get_pcm_device_id(adev->audio_route, uc_info->id,
1194 PCM_CAPTURE);
1195
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001196 if (pcm_dev_rx_id < 0 || pcm_dev_tx_id < 0) {
1197 ALOGE("%s: Invalid PCM devices (rx: %d tx: %d) for the usecase(%d)",
1198 __func__, pcm_dev_rx_id, pcm_dev_tx_id, uc_info->id);
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -08001199 ret = -EIO;
1200 goto error_start_voice;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001201 }
1202
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -08001203 ALOGV("%s: Opening PCM playback device card_id(%d) device_id(%d)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001204 __func__, SOUND_CARD, pcm_dev_rx_id);
1205 adev->voice_call_rx = pcm_open(SOUND_CARD,
1206 pcm_dev_rx_id,
1207 PCM_OUT, &pcm_config_voice_call);
1208 if (adev->voice_call_rx && !pcm_is_ready(adev->voice_call_rx)) {
1209 ALOGE("%s: %s", __func__, pcm_get_error(adev->voice_call_rx));
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -08001210 ret = -EIO;
1211 goto error_start_voice;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001212 }
1213
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -08001214 ALOGV("%s: Opening PCM capture device card_id(%d) device_id(%d)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001215 __func__, SOUND_CARD, pcm_dev_tx_id);
1216 adev->voice_call_tx = pcm_open(SOUND_CARD,
1217 pcm_dev_tx_id,
1218 PCM_IN, &pcm_config_voice_call);
1219 if (adev->voice_call_tx && !pcm_is_ready(adev->voice_call_tx)) {
1220 ALOGE("%s: %s", __func__, pcm_get_error(adev->voice_call_tx));
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -08001221 ret = -EIO;
1222 goto error_start_voice;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001223 }
1224 pcm_start(adev->voice_call_rx);
1225 pcm_start(adev->voice_call_tx);
1226
1227 if (adev->csd_client) {
1228 if (adev->csd_start_voice == NULL) {
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001229 ALOGE("dlsym error for csd_client_start_voice");
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -08001230 goto error_start_voice;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001231 } else {
1232 ret = adev->csd_start_voice();
1233 if (ret < 0) {
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -08001234 ALOGE("%s: csd_start_voice error %d\n", __func__, ret);
1235 goto error_start_voice;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001236 }
1237 }
1238 }
1239
1240 adev->in_call = true;
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -08001241 return 0;
1242
1243error_start_voice:
1244 stop_voice_call(adev);
1245
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001246 ALOGD("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001247 return ret;
1248}
1249
1250static int check_input_parameters(uint32_t sample_rate,
1251 audio_format_t format,
1252 int channel_count)
1253{
1254 if (format != AUDIO_FORMAT_PCM_16_BIT) return -EINVAL;
1255
1256 if ((channel_count < 1) || (channel_count > 2)) return -EINVAL;
1257
1258 switch (sample_rate) {
1259 case 8000:
1260 case 11025:
1261 case 12000:
1262 case 16000:
1263 case 22050:
1264 case 24000:
1265 case 32000:
1266 case 44100:
1267 case 48000:
1268 break;
1269 default:
1270 return -EINVAL;
1271 }
1272
1273 return 0;
1274}
1275
1276static size_t get_input_buffer_size(uint32_t sample_rate,
1277 audio_format_t format,
1278 int channel_count)
1279{
1280 size_t size = 0;
1281
1282 if (check_input_parameters(sample_rate, format, channel_count) != 0) return 0;
1283
1284 if (sample_rate == 8000 || sample_rate == 16000 || sample_rate == 32000) {
1285 size = (sample_rate * 20) / 1000;
1286 } else if (sample_rate == 11025 || sample_rate == 12000) {
1287 size = 256;
1288 } else if (sample_rate == 22050 || sample_rate == 24000) {
1289 size = 512;
1290 } else if (sample_rate == 44100 || sample_rate == 48000) {
1291 size = 1024;
1292 }
1293
1294 return size * sizeof(short) * channel_count;
1295}
1296
1297static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1298{
1299 struct stream_out *out = (struct stream_out *)stream;
1300
1301 return out->config.rate;
1302}
1303
1304static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
1305{
1306 return -ENOSYS;
1307}
1308
1309static size_t out_get_buffer_size(const struct audio_stream *stream)
1310{
1311 struct stream_out *out = (struct stream_out *)stream;
1312
1313 return out->config.period_size * audio_stream_frame_size(stream);
1314}
1315
1316static uint32_t out_get_channels(const struct audio_stream *stream)
1317{
1318 struct stream_out *out = (struct stream_out *)stream;
1319
1320 return out->channel_mask;
1321}
1322
1323static audio_format_t out_get_format(const struct audio_stream *stream)
1324{
1325 return AUDIO_FORMAT_PCM_16_BIT;
1326}
1327
1328static int out_set_format(struct audio_stream *stream, audio_format_t format)
1329{
1330 return -ENOSYS;
1331}
1332
1333static int out_standby(struct audio_stream *stream)
1334{
1335 struct stream_out *out = (struct stream_out *)stream;
1336 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001337 ALOGD("%s: enter: usecase(%d: %s)", __func__,
1338 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001339 pthread_mutex_lock(&out->lock);
1340
1341 if (!out->standby) {
1342 out->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08001343 if (out->pcm) {
1344 pcm_close(out->pcm);
1345 out->pcm = NULL;
1346 }
1347 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001348 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001349 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001350 }
1351 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001352 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001353 return 0;
1354}
1355
1356static int out_dump(const struct audio_stream *stream, int fd)
1357{
1358 return 0;
1359}
1360
1361static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1362{
1363 struct stream_out *out = (struct stream_out *)stream;
1364 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001365 struct audio_usecase *usecase;
1366 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001367 struct str_parms *parms;
1368 char value[32];
1369 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001370 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001371
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001372 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
1373 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001374 parms = str_parms_create_str(kvpairs);
1375 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1376 if (ret >= 0) {
1377 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001378 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001379 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001380
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001381 /*
1382 * When HDMI cable is unplugged the music playback is paused and
1383 * the policy manager sends routing=0. But the audioflinger
1384 * continues to write data until standby time (3sec).
1385 * As the HDMI core is turned off, the write gets blocked.
1386 * Avoid this by routing audio to speaker until standby.
1387 */
1388 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
1389 val == AUDIO_DEVICE_NONE) {
1390 val = AUDIO_DEVICE_OUT_SPEAKER;
1391 }
1392
1393 /*
1394 * select_devices() call below switches all the usecases on the same
1395 * backend to the new device. Refer to check_usecases_codec_backend() in
1396 * the select_devices(). But how do we undo this?
1397 *
1398 * For example, music playback is active on headset (deep-buffer usecase)
1399 * and if we go to ringtones and select a ringtone, low-latency usecase
1400 * will be started on headset+speaker. As we can't enable headset+speaker
1401 * and headset devices at the same time, select_devices() switches the music
1402 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1403 * So when the ringtone playback is completed, how do we undo the same?
1404 *
1405 * We are relying on the out_set_parameters() call on deep-buffer output,
1406 * once the ringtone playback is ended.
1407 * NOTE: We should not check if the current devices are same as new devices.
1408 * Because select_devices() must be called to switch back the music
1409 * playback to headset.
1410 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001411 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001412 out->devices = val;
1413
1414 if (!out->standby)
1415 select_devices(adev, out->usecase);
1416
1417 if ((adev->mode == AUDIO_MODE_IN_CALL) && !adev->in_call &&
1418 (out == adev->primary_output)) {
1419 start_voice_call(adev);
1420 } else if ((adev->mode == AUDIO_MODE_IN_CALL) && adev->in_call &&
1421 (out == adev->primary_output)) {
1422 select_devices(adev, USECASE_VOICE_CALL);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001423 }
1424 }
1425
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001426 if ((adev->mode != AUDIO_MODE_IN_CALL) && adev->in_call &&
1427 (out == adev->primary_output)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001428 stop_voice_call(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001429 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001430
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001431 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001432 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001433 }
1434 str_parms_destroy(parms);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001435 ALOGD("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001436 return ret;
1437}
1438
1439static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1440{
1441 struct stream_out *out = (struct stream_out *)stream;
1442 struct str_parms *query = str_parms_create_str(keys);
1443 char *str;
1444 char value[256];
1445 struct str_parms *reply = str_parms_create();
1446 size_t i, j;
1447 int ret;
1448 bool first = true;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001449 ALOGD("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001450 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1451 if (ret >= 0) {
1452 value[0] = '\0';
1453 i = 0;
1454 while (out->supported_channel_masks[i] != 0) {
1455 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1456 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1457 if (!first) {
1458 strcat(value, "|");
1459 }
1460 strcat(value, out_channels_name_to_enum_table[j].name);
1461 first = false;
1462 break;
1463 }
1464 }
1465 i++;
1466 }
1467 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1468 str = str_parms_to_str(reply);
1469 } else {
1470 str = strdup(keys);
1471 }
1472 str_parms_destroy(query);
1473 str_parms_destroy(reply);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001474 ALOGD("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001475 return str;
1476}
1477
1478static uint32_t out_get_latency(const struct audio_stream_out *stream)
1479{
1480 struct stream_out *out = (struct stream_out *)stream;
1481
1482 return (out->config.period_count * out->config.period_size * 1000) / (out->config.rate);
1483}
1484
1485static int out_set_volume(struct audio_stream_out *stream, float left,
1486 float right)
1487{
Eric Laurenta9024de2013-04-04 09:19:12 -07001488 struct stream_out *out = (struct stream_out *)stream;
1489 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1490 /* only take left channel into account: the API is for stereo anyway */
1491 out->muted = (left == 0.0f);
1492 return 0;
1493 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001494 return -ENOSYS;
1495}
1496
1497static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
1498 size_t bytes)
1499{
1500 struct stream_out *out = (struct stream_out *)stream;
1501 struct audio_device *adev = out->dev;
1502 int i, ret = -1;
1503
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001504 pthread_mutex_lock(&out->lock);
1505 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001506 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08001507 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001508 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001509 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001510 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001511 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001512 goto exit;
1513 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001514 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001515
1516 if (out->pcm) {
Eric Laurenta9024de2013-04-04 09:19:12 -07001517 if (out->muted)
1518 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001519 //ALOGV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
1520 ret = pcm_write(out->pcm, (void *)buffer, bytes);
1521 }
1522
1523exit:
1524 pthread_mutex_unlock(&out->lock);
1525
1526 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001527 if (out->pcm)
1528 ALOGE("%s: error %d - %s", __func__, ret, pcm_get_error(out->pcm));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001529 out_standby(&out->stream.common);
1530 usleep(bytes * 1000000 / audio_stream_frame_size(&out->stream.common) /
1531 out_get_sample_rate(&out->stream.common));
1532 }
1533 return bytes;
1534}
1535
1536static int out_get_render_position(const struct audio_stream_out *stream,
1537 uint32_t *dsp_frames)
1538{
1539 return -EINVAL;
1540}
1541
1542static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1543{
1544 return 0;
1545}
1546
1547static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1548{
1549 return 0;
1550}
1551
1552static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
1553 int64_t *timestamp)
1554{
1555 return -EINVAL;
1556}
1557
1558/** audio_stream_in implementation **/
1559static uint32_t in_get_sample_rate(const struct audio_stream *stream)
1560{
1561 struct stream_in *in = (struct stream_in *)stream;
1562
1563 return in->config.rate;
1564}
1565
1566static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
1567{
1568 return -ENOSYS;
1569}
1570
1571static size_t in_get_buffer_size(const struct audio_stream *stream)
1572{
1573 struct stream_in *in = (struct stream_in *)stream;
1574
1575 return in->config.period_size * audio_stream_frame_size(stream);
1576}
1577
1578static uint32_t in_get_channels(const struct audio_stream *stream)
1579{
1580 struct stream_in *in = (struct stream_in *)stream;
1581
1582 return in->channel_mask;
1583}
1584
1585static audio_format_t in_get_format(const struct audio_stream *stream)
1586{
1587 return AUDIO_FORMAT_PCM_16_BIT;
1588}
1589
1590static int in_set_format(struct audio_stream *stream, audio_format_t format)
1591{
1592 return -ENOSYS;
1593}
1594
1595static int in_standby(struct audio_stream *stream)
1596{
1597 struct stream_in *in = (struct stream_in *)stream;
1598 struct audio_device *adev = in->dev;
1599 int status = 0;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001600 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001601 pthread_mutex_lock(&in->lock);
1602 if (!in->standby) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001603 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08001604 if (in->pcm) {
1605 pcm_close(in->pcm);
1606 in->pcm = NULL;
1607 }
1608 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001609 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001610 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001611 }
1612 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001613 ALOGD("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001614 return status;
1615}
1616
1617static int in_dump(const struct audio_stream *stream, int fd)
1618{
1619 return 0;
1620}
1621
1622static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
1623{
1624 struct stream_in *in = (struct stream_in *)stream;
1625 struct audio_device *adev = in->dev;
1626 struct str_parms *parms;
1627 char *str;
1628 char value[32];
1629 int ret, val = 0;
1630
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001631 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001632 parms = str_parms_create_str(kvpairs);
1633
1634 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
1635
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001636 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001637 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001638 if (ret >= 0) {
1639 val = atoi(value);
1640 /* no audio source uses val == 0 */
1641 if ((in->source != val) && (val != 0)) {
1642 in->source = val;
1643 }
1644 }
1645
1646 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1647 if (ret >= 0) {
1648 val = atoi(value);
1649 if ((in->device != val) && (val != 0)) {
1650 in->device = val;
1651 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001652 if (!in->standby)
1653 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001654 }
1655 }
1656
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001657 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001658 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001659
1660 str_parms_destroy(parms);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001661 ALOGD("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001662 return ret;
1663}
1664
1665static char* in_get_parameters(const struct audio_stream *stream,
1666 const char *keys)
1667{
1668 return strdup("");
1669}
1670
1671static int in_set_gain(struct audio_stream_in *stream, float gain)
1672{
1673 return 0;
1674}
1675
1676static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
1677 size_t bytes)
1678{
1679 struct stream_in *in = (struct stream_in *)stream;
1680 struct audio_device *adev = in->dev;
1681 int i, ret = -1;
1682
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001683 pthread_mutex_lock(&in->lock);
1684 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001685 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001686 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001687 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001688 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001689 goto exit;
1690 }
1691 in->standby = 0;
1692 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001693
1694 if (in->pcm) {
1695 ret = pcm_read(in->pcm, buffer, bytes);
1696 }
1697
1698 /*
1699 * Instead of writing zeroes here, we could trust the hardware
1700 * to always provide zeroes when muted.
1701 */
1702 if (ret == 0 && adev->mic_mute)
1703 memset(buffer, 0, bytes);
1704
1705exit:
1706 pthread_mutex_unlock(&in->lock);
1707
1708 if (ret != 0) {
1709 in_standby(&in->stream.common);
1710 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
1711 usleep(bytes * 1000000 / audio_stream_frame_size(&in->stream.common) /
1712 in_get_sample_rate(&in->stream.common));
1713 }
1714 return bytes;
1715}
1716
1717static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
1718{
1719 return 0;
1720}
1721
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001722static int add_remove_audio_effect(const struct audio_stream *stream,
1723 effect_handle_t effect,
1724 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001725{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001726 struct stream_in *in = (struct stream_in *)stream;
1727 int status = 0;
1728 effect_descriptor_t desc;
1729
1730 status = (*effect)->get_descriptor(effect, &desc);
1731 if (status != 0)
1732 return status;
1733
1734 pthread_mutex_lock(&in->lock);
1735 pthread_mutex_lock(&in->dev->lock);
1736 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
1737 in->enable_aec != enable &&
1738 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
1739 in->enable_aec = enable;
1740 if (!in->standby)
1741 select_devices(in->dev, in->usecase);
1742 }
1743 pthread_mutex_unlock(&in->dev->lock);
1744 pthread_mutex_unlock(&in->lock);
1745
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001746 return 0;
1747}
1748
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001749static int in_add_audio_effect(const struct audio_stream *stream,
1750 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001751{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001752 ALOGD("%s: effect %p", __func__, effect);
1753 return add_remove_audio_effect(stream, effect, true);
1754}
1755
1756static int in_remove_audio_effect(const struct audio_stream *stream,
1757 effect_handle_t effect)
1758{
1759 ALOGD("%s: effect %p", __func__, effect);
1760 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001761}
1762
1763static int adev_open_output_stream(struct audio_hw_device *dev,
1764 audio_io_handle_t handle,
1765 audio_devices_t devices,
1766 audio_output_flags_t flags,
1767 struct audio_config *config,
1768 struct audio_stream_out **stream_out)
1769{
1770 struct audio_device *adev = (struct audio_device *)dev;
1771 struct stream_out *out;
1772 int i, ret;
1773
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001774 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001775 __func__, config->sample_rate, config->channel_mask, devices, flags);
1776 *stream_out = NULL;
1777 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
1778
1779 if (devices == AUDIO_DEVICE_NONE)
1780 devices = AUDIO_DEVICE_OUT_SPEAKER;
1781
1782 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
1783 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
1784 out->flags = flags;
1785 out->devices = devices;
1786
1787 /* Init use case and pcm_config */
1788 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
1789 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001790 pthread_mutex_lock(&adev->lock);
1791 ret = read_hdmi_channel_masks(out);
1792 pthread_mutex_unlock(&adev->lock);
1793 if (ret != 0) {
1794 /* If HDMI does not support multi channel playback, set the default */
1795 out->config.channels = popcount(out->channel_mask);
1796 set_hdmi_channels(adev->mixer, out->config.channels);
1797 goto error_open;
1798 }
1799
1800 if (config->sample_rate == 0)
1801 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1802 if (config->channel_mask == 0)
1803 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
1804
1805 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001806 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
1807 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001808 out->config.rate = config->sample_rate;
1809 out->config.channels = popcount(out->channel_mask);
1810 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
1811 set_hdmi_channels(adev->mixer, out->config.channels);
1812 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
1813 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
1814 out->config = pcm_config_deep_buffer;
1815 } else {
1816 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
1817 out->config = pcm_config_low_latency;
1818 }
1819
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001820 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
1821 if(adev->primary_output == NULL)
1822 adev->primary_output = out;
1823 else {
1824 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001825 ret = -EEXIST;
1826 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001827 }
1828 }
1829
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001830 /* Check if this usecase is already existing */
1831 pthread_mutex_lock(&adev->lock);
1832 if (get_usecase_from_list(adev, out->usecase) != NULL) {
1833 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001834 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001835 ret = -EEXIST;
1836 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001837 }
1838 pthread_mutex_unlock(&adev->lock);
1839
1840 out->stream.common.get_sample_rate = out_get_sample_rate;
1841 out->stream.common.set_sample_rate = out_set_sample_rate;
1842 out->stream.common.get_buffer_size = out_get_buffer_size;
1843 out->stream.common.get_channels = out_get_channels;
1844 out->stream.common.get_format = out_get_format;
1845 out->stream.common.set_format = out_set_format;
1846 out->stream.common.standby = out_standby;
1847 out->stream.common.dump = out_dump;
1848 out->stream.common.set_parameters = out_set_parameters;
1849 out->stream.common.get_parameters = out_get_parameters;
1850 out->stream.common.add_audio_effect = out_add_audio_effect;
1851 out->stream.common.remove_audio_effect = out_remove_audio_effect;
1852 out->stream.get_latency = out_get_latency;
1853 out->stream.set_volume = out_set_volume;
1854 out->stream.write = out_write;
1855 out->stream.get_render_position = out_get_render_position;
1856 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
1857
1858 out->dev = adev;
1859 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07001860 /* out->muted = false; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001861
1862 config->format = out->stream.common.get_format(&out->stream.common);
1863 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
1864 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
1865
1866 *stream_out = &out->stream;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001867 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001868 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001869
1870error_open:
1871 free(out);
1872 *stream_out = NULL;
1873 ALOGD("%s: exit: ret %d", __func__, ret);
1874 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001875}
1876
1877static void adev_close_output_stream(struct audio_hw_device *dev,
1878 struct audio_stream_out *stream)
1879{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001880 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001881 out_standby(&stream->common);
1882 free(stream);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001883 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001884}
1885
1886static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
1887{
1888 struct audio_device *adev = (struct audio_device *)dev;
1889 struct str_parms *parms;
1890 char *str;
1891 char value[32];
1892 int ret;
1893
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001894 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001895
1896 parms = str_parms_create_str(kvpairs);
1897 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_TTY_MODE, value, sizeof(value));
1898 if (ret >= 0) {
1899 int tty_mode;
1900
1901 if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_OFF) == 0)
1902 tty_mode = TTY_MODE_OFF;
1903 else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_VCO) == 0)
1904 tty_mode = TTY_MODE_VCO;
1905 else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_HCO) == 0)
1906 tty_mode = TTY_MODE_HCO;
1907 else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_FULL) == 0)
1908 tty_mode = TTY_MODE_FULL;
1909 else
1910 return -EINVAL;
1911
1912 pthread_mutex_lock(&adev->lock);
1913 if (tty_mode != adev->tty_mode) {
1914 adev->tty_mode = tty_mode;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08001915 adev->acdb_settings = (adev->acdb_settings & TTY_MODE_CLEAR) | tty_mode;
1916 if (adev->in_call)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001917 select_devices(adev, USECASE_VOICE_CALL);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001918 }
1919 pthread_mutex_unlock(&adev->lock);
1920 }
1921
1922 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
1923 if (ret >= 0) {
1924 /* When set to false, HAL should disable EC and NS
1925 * But it is currently not supported.
1926 */
1927 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
1928 adev->bluetooth_nrec = true;
1929 else
1930 adev->bluetooth_nrec = false;
1931 }
1932
1933 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
1934 if (ret >= 0) {
1935 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
1936 adev->screen_off = false;
1937 else
1938 adev->screen_off = true;
1939 }
1940
1941 str_parms_destroy(parms);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001942 ALOGD("%s: exit with code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001943 return ret;
1944}
1945
1946static char* adev_get_parameters(const struct audio_hw_device *dev,
1947 const char *keys)
1948{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001949 return strdup("");
1950}
1951
1952static int adev_init_check(const struct audio_hw_device *dev)
1953{
1954 return 0;
1955}
1956
1957static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
1958{
1959 struct audio_device *adev = (struct audio_device *)dev;
1960 int vol, err = 0;
1961
1962 pthread_mutex_lock(&adev->lock);
1963 adev->voice_volume = volume;
1964 if (adev->mode == AUDIO_MODE_IN_CALL) {
1965 if (volume < 0.0) {
1966 volume = 0.0;
1967 } else if (volume > 1.0) {
1968 volume = 1.0;
1969 }
1970
1971 vol = lrint(volume * 100.0);
1972
1973 // Voice volume levels from android are mapped to driver volume levels as follows.
1974 // 0 -> 5, 20 -> 4, 40 ->3, 60 -> 2, 80 -> 1, 100 -> 0
1975 // So adjust the volume to get the correct volume index in driver
1976 vol = 100 - vol;
Ravi Kumar Alamanda87f6ee02013-05-07 14:20:11 -07001977#ifdef MSM8974
1978 set_voice_volume(adev->mixer, vol);
1979#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001980 if (adev->csd_client) {
1981 if (adev->csd_volume == NULL) {
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001982 ALOGE("%s: dlsym error for csd_client_volume", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001983 } else {
1984 err = adev->csd_volume(vol);
1985 if (err < 0) {
1986 ALOGE("%s: csd_client error %d", __func__, err);
1987 }
1988 }
1989 } else {
1990 ALOGE("%s: No CSD Client present", __func__);
1991 }
Ravi Kumar Alamanda87f6ee02013-05-07 14:20:11 -07001992#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001993 }
1994 pthread_mutex_unlock(&adev->lock);
1995 return err;
1996}
1997
1998static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
1999{
2000 return -ENOSYS;
2001}
2002
2003static int adev_get_master_volume(struct audio_hw_device *dev,
2004 float *volume)
2005{
2006 return -ENOSYS;
2007}
2008
2009static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
2010{
2011 return -ENOSYS;
2012}
2013
2014static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
2015{
2016 return -ENOSYS;
2017}
2018
2019static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
2020{
2021 struct audio_device *adev = (struct audio_device *)dev;
2022
2023 pthread_mutex_lock(&adev->lock);
2024 if (adev->mode != mode) {
2025 adev->mode = mode;
2026 }
2027 pthread_mutex_unlock(&adev->lock);
2028 return 0;
2029}
2030
2031static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
2032{
2033 struct audio_device *adev = (struct audio_device *)dev;
2034 int err = 0;
2035
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002036 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002037 adev->mic_mute = state;
2038 if (adev->mode == AUDIO_MODE_IN_CALL) {
Ravi Kumar Alamanda87f6ee02013-05-07 14:20:11 -07002039#ifdef MSM8974
2040 set_mic_mute(adev->mixer, state);
2041#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002042 if (adev->csd_client) {
2043 if (adev->csd_mic_mute == NULL) {
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002044 ALOGE("%s: dlsym error for csd_mic_mute", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002045 } else {
2046 err = adev->csd_mic_mute(state);
2047 if (err < 0) {
2048 ALOGE("%s: csd_client error %d", __func__, err);
2049 }
2050 }
2051 } else {
2052 ALOGE("%s: No CSD Client present", __func__);
2053 }
Ravi Kumar Alamanda87f6ee02013-05-07 14:20:11 -07002054#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002055 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002056 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002057 return err;
2058}
2059
2060static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
2061{
2062 struct audio_device *adev = (struct audio_device *)dev;
2063
2064 *state = adev->mic_mute;
2065
2066 return 0;
2067}
2068
2069static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
2070 const struct audio_config *config)
2071{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002072 int channel_count = popcount(config->channel_mask);
2073
2074 return get_input_buffer_size(config->sample_rate, config->format, channel_count);
2075}
2076
2077static int adev_open_input_stream(struct audio_hw_device *dev,
2078 audio_io_handle_t handle,
2079 audio_devices_t devices,
2080 struct audio_config *config,
2081 struct audio_stream_in **stream_in)
2082{
2083 struct audio_device *adev = (struct audio_device *)dev;
2084 struct stream_in *in;
2085 int ret, buffer_size, frame_size;
2086 int channel_count = popcount(config->channel_mask);
2087
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002088 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002089 *stream_in = NULL;
2090 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
2091 return -EINVAL;
2092
2093 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
2094
2095 in->stream.common.get_sample_rate = in_get_sample_rate;
2096 in->stream.common.set_sample_rate = in_set_sample_rate;
2097 in->stream.common.get_buffer_size = in_get_buffer_size;
2098 in->stream.common.get_channels = in_get_channels;
2099 in->stream.common.get_format = in_get_format;
2100 in->stream.common.set_format = in_set_format;
2101 in->stream.common.standby = in_standby;
2102 in->stream.common.dump = in_dump;
2103 in->stream.common.set_parameters = in_set_parameters;
2104 in->stream.common.get_parameters = in_get_parameters;
2105 in->stream.common.add_audio_effect = in_add_audio_effect;
2106 in->stream.common.remove_audio_effect = in_remove_audio_effect;
2107 in->stream.set_gain = in_set_gain;
2108 in->stream.read = in_read;
2109 in->stream.get_input_frames_lost = in_get_input_frames_lost;
2110
2111 in->device = devices;
2112 in->source = AUDIO_SOURCE_DEFAULT;
2113 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002114 in->standby = 1;
2115 in->channel_mask = config->channel_mask;
2116
2117 /* Update config params with the requested sample rate and channels */
2118 in->usecase = USECASE_AUDIO_RECORD;
2119 in->config = pcm_config_audio_capture;
2120 in->config.channels = channel_count;
2121 in->config.rate = config->sample_rate;
2122
2123 frame_size = audio_stream_frame_size((struct audio_stream *)in);
2124 buffer_size = get_input_buffer_size(config->sample_rate,
2125 config->format,
2126 channel_count);
2127 in->config.period_size = buffer_size / frame_size;
2128
2129 *stream_in = &in->stream;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002130 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002131 return 0;
2132
2133err_open:
2134 free(in);
2135 *stream_in = NULL;
2136 return ret;
2137}
2138
2139static void adev_close_input_stream(struct audio_hw_device *dev,
2140 struct audio_stream_in *stream)
2141{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002142 ALOGD("%s", __func__);
2143
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002144 in_standby(&stream->common);
2145 free(stream);
2146
2147 return;
2148}
2149
2150static int adev_dump(const audio_hw_device_t *device, int fd)
2151{
2152 return 0;
2153}
2154
2155static int adev_close(hw_device_t *device)
2156{
2157 struct audio_device *adev = (struct audio_device *)device;
2158 audio_route_free(adev->audio_route);
2159 free(device);
2160 return 0;
2161}
2162
2163static void init_platform_data(struct audio_device *adev)
2164{
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -08002165 char platform[PROPERTY_VALUE_MAX];
2166 char baseband[PROPERTY_VALUE_MAX];
2167 char value[PROPERTY_VALUE_MAX];
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -08002168
2169 adev->dualmic_config = DUALMIC_CONFIG_NONE;
Ravi Kumar Alamanda02317792013-03-04 20:56:50 -08002170 adev->fluence_in_spkr_mode = false;
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -08002171 adev->fluence_in_voice_call = false;
2172 adev->fluence_in_voice_rec = false;
2173 adev->mic_type_analog = false;
2174
2175 property_get("persist.audio.handset.mic.type",value,"");
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002176 if (!strcmp("analog", value))
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -08002177 adev->mic_type_analog = true;
2178
2179 property_get("persist.audio.dualmic.config",value,"");
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002180 if (!strcmp("broadside", value)) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -08002181 adev->dualmic_config = DUALMIC_CONFIG_BROADSIDE;
2182 adev->acdb_settings |= DMIC_FLAG;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002183 } else if (!strcmp("endfire", value)) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -08002184 adev->dualmic_config = DUALMIC_CONFIG_ENDFIRE;
2185 adev->acdb_settings |= DMIC_FLAG;
2186 }
2187
2188 if (adev->dualmic_config != DUALMIC_CONFIG_NONE) {
2189 property_get("persist.audio.fluence.voicecall",value,"");
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002190 if (!strcmp("true", value)) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -08002191 adev->fluence_in_voice_call = true;
2192 }
2193
2194 property_get("persist.audio.fluence.voicerec",value,"");
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002195 if (!strcmp("true", value)) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -08002196 adev->fluence_in_voice_rec = true;
2197 }
Ravi Kumar Alamanda02317792013-03-04 20:56:50 -08002198
2199 property_get("persist.audio.fluence.speaker",value,"");
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002200 if (!strcmp("true", value)) {
Ravi Kumar Alamanda02317792013-03-04 20:56:50 -08002201 adev->fluence_in_spkr_mode = true;
2202 }
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -08002203 }
2204
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002205 adev->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
2206 if (adev->acdb_handle == NULL) {
2207 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_ACDB_LOADER);
2208 } else {
2209 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_ACDB_LOADER);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002210 adev->acdb_deallocate = (acdb_deallocate_t)dlsym(adev->acdb_handle,
2211 "acdb_loader_deallocate_ACDB");
2212 adev->acdb_send_audio_cal = (acdb_send_audio_cal_t)dlsym(adev->acdb_handle,
2213 "acdb_loader_send_audio_cal");
2214 adev->acdb_send_voice_cal = (acdb_send_voice_cal_t)dlsym(adev->acdb_handle,
2215 "acdb_loader_send_voice_cal");
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002216 adev->acdb_init = (acdb_init_t)dlsym(adev->acdb_handle,
2217 "acdb_loader_init_ACDB");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002218 if (adev->acdb_init == NULL)
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002219 ALOGE("%s: dlsym error %s for acdb_loader_init_ACDB", __func__, dlerror());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002220 else
2221 adev->acdb_init();
2222 }
2223
2224 /* If platform is Fusion3, load CSD Client specific symbols
2225 * Voice call is handled by MDM and apps processor talks to
2226 * MDM through CSD Client
2227 */
2228 property_get("ro.board.platform", platform, "");
2229 property_get("ro.baseband", baseband, "");
2230 if (!strcmp("msm8960", platform) && !strcmp("mdm", baseband)) {
2231 adev->csd_client = dlopen(LIB_CSD_CLIENT, RTLD_NOW);
2232 if (adev->csd_client == NULL)
2233 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_CSD_CLIENT);
2234 }
2235
2236 if (adev->csd_client) {
2237 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_CSD_CLIENT);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002238 adev->csd_client_deinit = (csd_client_deinit_t)dlsym(adev->csd_client,
2239 "csd_client_deinit");
2240 adev->csd_disable_device = (csd_disable_device_t)dlsym(adev->csd_client,
2241 "csd_client_disable_device");
2242 adev->csd_enable_device = (csd_enable_device_t)dlsym(adev->csd_client,
2243 "csd_client_enable_device");
2244 adev->csd_start_voice = (csd_start_voice_t)dlsym(adev->csd_client,
2245 "csd_client_start_voice");
2246 adev->csd_stop_voice = (csd_stop_voice_t)dlsym(adev->csd_client,
2247 "csd_client_stop_voice");
2248 adev->csd_volume = (csd_volume_t)dlsym(adev->csd_client,
2249 "csd_client_volume");
2250 adev->csd_mic_mute = (csd_mic_mute_t)dlsym(adev->csd_client,
2251 "csd_client_mic_mute");
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002252 adev->csd_client_init = (csd_client_init_t)dlsym(adev->csd_client,
2253 "csd_client_init");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254
2255 if (adev->csd_client_init == NULL) {
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002256 ALOGE("%s: dlsym error %s for csd_client_init", __func__, dlerror());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002257 } else {
2258 adev->csd_client_init();
2259 }
2260 }
2261}
2262
2263static int adev_open(const hw_module_t *module, const char *name,
2264 hw_device_t **device)
2265{
2266 struct audio_device *adev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002267 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002268
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002269 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002270 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
2271
2272 adev = calloc(1, sizeof(struct audio_device));
2273
2274 adev->mixer = mixer_open(MIXER_CARD);
2275 if (!adev->mixer) {
2276 ALOGE("Unable to open the mixer, aborting.");
2277 return -ENOSYS;
2278 }
2279
2280 adev->audio_route = audio_route_init(MIXER_CARD, MIXER_XML_PATH);
2281 if (!adev->audio_route) {
2282 free(adev);
2283 ALOGE("%s: Failed to init audio route controls, aborting.", __func__);
2284 *device = NULL;
2285 return -EINVAL;
2286 }
2287
2288 adev->device.common.tag = HARDWARE_DEVICE_TAG;
2289 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
2290 adev->device.common.module = (struct hw_module_t *)module;
2291 adev->device.common.close = adev_close;
2292
2293 adev->device.init_check = adev_init_check;
2294 adev->device.set_voice_volume = adev_set_voice_volume;
2295 adev->device.set_master_volume = adev_set_master_volume;
2296 adev->device.get_master_volume = adev_get_master_volume;
2297 adev->device.set_master_mute = adev_set_master_mute;
2298 adev->device.get_master_mute = adev_get_master_mute;
2299 adev->device.set_mode = adev_set_mode;
2300 adev->device.set_mic_mute = adev_set_mic_mute;
2301 adev->device.get_mic_mute = adev_get_mic_mute;
2302 adev->device.set_parameters = adev_set_parameters;
2303 adev->device.get_parameters = adev_get_parameters;
2304 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
2305 adev->device.open_output_stream = adev_open_output_stream;
2306 adev->device.close_output_stream = adev_close_output_stream;
2307 adev->device.open_input_stream = adev_open_input_stream;
2308 adev->device.close_input_stream = adev_close_input_stream;
2309 adev->device.dump = adev_dump;
2310
2311 /* Set the default route before the PCM stream is opened */
2312 pthread_mutex_lock(&adev->lock);
2313 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08002314 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002315 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002316 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002317 adev->voice_call_rx = NULL;
2318 adev->voice_call_tx = NULL;
2319 adev->voice_volume = 1.0f;
2320 adev->tty_mode = TTY_MODE_OFF;
2321 adev->bluetooth_nrec = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002322 adev->in_call = false;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08002323 adev->acdb_settings = TTY_MODE_OFF;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002324 for (i = 0; i < SND_DEVICE_MAX; i++) {
2325 adev->snd_dev_ref_cnt[i] = 0;
2326 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002327 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002328 pthread_mutex_unlock(&adev->lock);
2329
2330 /* Loads platform specific libraries dynamically */
2331 init_platform_data(adev);
2332
2333 *device = &adev->device.common;
2334
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002335 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002336 return 0;
2337}
2338
2339static struct hw_module_methods_t hal_module_methods = {
2340 .open = adev_open,
2341};
2342
2343struct audio_module HAL_MODULE_INFO_SYM = {
2344 .common = {
2345 .tag = HARDWARE_MODULE_TAG,
2346 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
2347 .hal_api_version = HARDWARE_HAL_API_VERSION,
2348 .id = AUDIO_HARDWARE_MODULE_ID,
2349 .name = "QCOM Audio HAL",
2350 .author = "Code Aurora Forum",
2351 .methods = &hal_module_methods,
2352 },
2353};