blob: 7ded47171551d5df6bd8b06a6cc2dcfe9c992e09 [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
Sungmin Choi75ebaa02013-05-22 13:14:28 -070036#define LIB_ACDB_LOADER "libacdbloader.so"
37#define LIB_CSD_CLIENT "libcsd-client.so"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080038#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";
sangwoofbf5d512013-05-20 11:38:45 +0900527
528 // Voice volume levels are mapped to adsp volume levels as follows.
529 // 100 -> 5, 80 -> 4, 60 -> 3, 40 -> 2, 20 -> 1 0 -> 0
530 // But this values don't changed in kernel. So, below change is need.
531 volume = volume / 20;
532
Ravi Kumar Alamanda87f6ee02013-05-07 14:20:11 -0700533 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
534 if (!ctl) {
535 ALOGE("%s: Could not get ctl for mixer cmd - %s",
536 __func__, mixer_ctl_name);
537 return -EINVAL;
538 }
539 ALOGV("Setting voice volume: %d", volume);
540 mixer_ctl_set_value(ctl, 0, volume);
541 return 0;
542}
543
544static int set_mic_mute(struct mixer *mixer,
545 int mute)
546{
547 struct mixer_ctl *ctl;
548 const char *mixer_ctl_name = "Voice Tx Mute";
549 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
550 if (!ctl) {
551 ALOGE("%s: Could not get ctl for mixer cmd - %s",
552 __func__, mixer_ctl_name);
553 return -EINVAL;
554 }
555 ALOGV("Setting mic mute: %d", mute);
556 mixer_ctl_set_value(ctl, 0, mute);
557 return 0;
558}
559
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700560static snd_device_t get_output_snd_device(struct audio_device *adev,
561 audio_devices_t devices)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800562{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700563 audio_mode_t mode = adev->mode;
564 snd_device_t snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800565
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800566 ALOGV("%s: enter: output devices(%#x)", __func__, devices);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800567 if (devices == AUDIO_DEVICE_NONE ||
568 devices & AUDIO_DEVICE_BIT_IN) {
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800569 ALOGV("%s: Invalid output devices (%#x)", __func__, devices);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800570 goto exit;
571 }
572
573 if (mode == AUDIO_MODE_IN_CALL) {
574 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
575 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800576 if (adev->tty_mode == TTY_MODE_FULL)
577 snd_device = SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES;
578 else if (adev->tty_mode == TTY_MODE_VCO)
579 snd_device = SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES;
580 else if (adev->tty_mode == TTY_MODE_HCO)
581 snd_device = SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET;
582 else
583 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800584 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
585 snd_device = SND_DEVICE_OUT_BT_SCO;
586 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
587 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
588 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
Ravi Kumar Alamanda37718842013-02-22 18:44:45 -0800589 if (is_operator_tmus())
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800590 snd_device = SND_DEVICE_OUT_VOICE_HANDSET_TMUS;
591 else
592 snd_device = SND_DEVICE_OUT_HANDSET;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800593 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800594 if (snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800595 goto exit;
596 }
597 }
598
599 if (popcount(devices) == 2) {
600 if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
601 AUDIO_DEVICE_OUT_SPEAKER)) {
602 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
603 } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
604 AUDIO_DEVICE_OUT_SPEAKER)) {
605 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
606 } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL |
607 AUDIO_DEVICE_OUT_SPEAKER)) {
608 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
609 } else {
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800610 ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800611 goto exit;
612 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800613 if (snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800614 goto exit;
615 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800616 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800617
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800618 if (popcount(devices) != 1) {
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800619 ALOGE("%s: Invalid output devices(%#x)", __func__, devices);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800620 goto exit;
621 }
622
623 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
624 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
625 snd_device = SND_DEVICE_OUT_HEADPHONES;
626 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
627 snd_device = SND_DEVICE_OUT_SPEAKER;
628 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
629 snd_device = SND_DEVICE_OUT_BT_SCO;
630 } else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
631 snd_device = SND_DEVICE_OUT_HDMI ;
632 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
633 snd_device = SND_DEVICE_OUT_HANDSET;
634 } else {
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800635 ALOGE("%s: Unknown device(s) %#x", __func__, devices);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800636 }
637exit:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800638 ALOGV("%s: exit: snd_device(%s)", __func__, device_table[snd_device]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800639 return snd_device;
640}
641
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700642static snd_device_t get_input_snd_device(struct audio_device *adev,
643 audio_devices_t out_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800644{
Eric Laurentc8400632013-02-14 19:04:54 -0800645 audio_source_t source = (adev->active_input == NULL) ?
646 AUDIO_SOURCE_DEFAULT : adev->active_input->source;
647
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800648 audio_mode_t mode = adev->mode;
Eric Laurentc8400632013-02-14 19:04:54 -0800649 audio_devices_t in_device = ((adev->active_input == NULL) ?
650 AUDIO_DEVICE_NONE : adev->active_input->device)
651 & ~AUDIO_DEVICE_BIT_IN;
652 audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
653 AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800654 snd_device_t snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800655
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800656 ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800657 __func__, out_device, in_device);
658 if (mode == AUDIO_MODE_IN_CALL) {
659 if (out_device == AUDIO_DEVICE_NONE) {
660 ALOGE("%s: No output device set for voice call", __func__);
661 goto exit;
662 }
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800663 if (adev->tty_mode != TTY_MODE_OFF) {
664 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
665 out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
666 switch (adev->tty_mode) {
667 case TTY_MODE_FULL:
668 snd_device = SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC;
669 break;
670 case TTY_MODE_VCO:
671 snd_device = SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC;
672 break;
673 case TTY_MODE_HCO:
674 snd_device = SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC;
675 break;
676 default:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800677 ALOGE("%s: Invalid TTY mode (%#x)", __func__, adev->tty_mode);
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800678 }
679 goto exit;
680 }
681 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800682 if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
683 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800684 if (adev->mic_type_analog || adev->fluence_in_voice_call == false) {
685 snd_device = SND_DEVICE_IN_HANDSET_MIC;
686 } else {
687 if (adev->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
Ravi Kumar Alamanda37718842013-02-22 18:44:45 -0800688 if (is_operator_tmus())
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800689 snd_device = SND_DEVICE_IN_VOICE_DMIC_EF_TMUS;
690 else
691 snd_device = SND_DEVICE_IN_VOICE_DMIC_EF;
692 } else if(adev->dualmic_config == DUALMIC_CONFIG_BROADSIDE)
693 snd_device = SND_DEVICE_IN_VOICE_DMIC_BS;
694 else
695 snd_device = SND_DEVICE_IN_HANDSET_MIC;
696 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800697 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
698 snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
699 } else if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
700 snd_device = SND_DEVICE_IN_BT_SCO_MIC ;
701 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
Ravi Kumar Alamanda02317792013-03-04 20:56:50 -0800702 if (adev->fluence_in_voice_call && adev->fluence_in_spkr_mode &&
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800703 adev->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
704 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF;
Ravi Kumar Alamanda02317792013-03-04 20:56:50 -0800705 } else if (adev->fluence_in_voice_call && adev->fluence_in_spkr_mode &&
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800706 adev->dualmic_config == DUALMIC_CONFIG_BROADSIDE) {
707 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS;
708 } else {
709 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
710 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800711 }
712 } else if (source == AUDIO_SOURCE_CAMCORDER) {
713 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
714 in_device & AUDIO_DEVICE_IN_BACK_MIC) {
715 snd_device = SND_DEVICE_IN_CAMCORDER_MIC;
716 }
717 } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) {
718 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
Eric Laurentc8400632013-02-14 19:04:54 -0800719 if (adev->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
720 if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
721 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_EF;
722 else if (adev->fluence_in_voice_rec)
723 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE;
Eric Laurentc8400632013-02-14 19:04:54 -0800724 } else if (adev->dualmic_config == DUALMIC_CONFIG_BROADSIDE) {
725 if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
726 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_BS;
727 else if (adev->fluence_in_voice_rec)
728 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -0700729 }
730
731 if (snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800732 snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -0700733 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800734 }
Ravi Kumar Alamanda8455fa72013-02-19 14:53:19 -0800735 } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
736 if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
737 in_device = AUDIO_DEVICE_IN_BACK_MIC;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -0700738 if (adev->active_input) {
739 if (adev->active_input->enable_aec) {
740 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
741 if (adev->mic_type_analog)
742 snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
743 else
744 snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
745 } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
746 snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
747 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
748 snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
749 }
750 set_echo_reference(adev->mixer, "SLIM_RX");
751 } else
752 set_echo_reference(adev->mixer, "NONE");
753 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800754 } else if (source == AUDIO_SOURCE_DEFAULT) {
755 goto exit;
756 }
757
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -0700758
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800759 if (snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800760 goto exit;
761 }
762
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800763 if (in_device != AUDIO_DEVICE_NONE &&
Ravi Kumar Alamanda8455fa72013-02-19 14:53:19 -0800764 !(in_device & AUDIO_DEVICE_IN_VOICE_CALL) &&
765 !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800766 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800767 snd_device = SND_DEVICE_IN_HANDSET_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800768 } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800769 if (adev->mic_type_analog)
770 snd_device = SND_DEVICE_IN_HANDSET_MIC;
771 else
772 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800773 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
774 snd_device = SND_DEVICE_IN_HEADSET_MIC;
775 } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
776 snd_device = SND_DEVICE_IN_BT_SCO_MIC ;
777 } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) {
778 snd_device = SND_DEVICE_IN_HDMI_MIC;
779 } else {
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800780 ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800781 ALOGW("%s: Using default handset-mic", __func__);
782 snd_device = SND_DEVICE_IN_HANDSET_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800783 }
784 } else {
785 if (out_device & AUDIO_DEVICE_OUT_EARPIECE) {
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_WIRED_HEADSET) {
788 snd_device = SND_DEVICE_IN_HEADSET_MIC;
789 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
790 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
791 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800792 snd_device = SND_DEVICE_IN_HANDSET_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800793 } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800794 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800795 } else if (out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
796 snd_device = SND_DEVICE_IN_HDMI_MIC;
797 } else {
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800798 ALOGE("%s: Unknown output device(s) %#x", __func__, out_device);
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -0800799 ALOGW("%s: Using default handset-mic", __func__);
800 snd_device = SND_DEVICE_IN_HANDSET_MIC;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800801 }
802 }
803exit:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800804 ALOGV("%s: exit: in_snd_device(%s)", __func__, device_table[snd_device]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800805 return snd_device;
806}
807
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700808static struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
809 audio_usecase_t uc_id)
810{
811 struct audio_usecase *usecase;
812 struct listnode *node;
813
814 list_for_each(node, &adev->usecase_list) {
815 usecase = node_to_item(node, struct audio_usecase, list);
816 if (usecase->id == uc_id)
817 return usecase;
818 }
819 return NULL;
820}
821
822static int select_devices(struct audio_device *adev,
823 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800824{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800825 snd_device_t out_snd_device = SND_DEVICE_NONE;
826 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700827 struct audio_usecase *usecase = NULL;
828 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800829 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800830 int acdb_rx_id, acdb_tx_id;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700831 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800832
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700833 usecase = get_usecase_from_list(adev, uc_id);
834 if (usecase == NULL) {
835 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
836 return -EINVAL;
837 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800838
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700839 if (usecase->type == VOICE_CALL) {
840 out_snd_device = get_output_snd_device(adev, usecase->stream.out->devices);
841 in_snd_device = get_input_snd_device(adev, usecase->stream.out->devices);
842 usecase->devices = usecase->stream.out->devices;
843 } else {
844 /*
845 * If the voice call is active, use the sound devices of voice call usecase
846 * so that it would not result any device switch. All the usecases will
847 * be switched to new device when select_devices() is called for voice call
848 * usecase. This is to avoid switching devices for voice call when
849 * check_usecases_codec_backend() is called below.
850 */
851 if (adev->in_call) {
852 vc_usecase = get_usecase_from_list(adev, USECASE_VOICE_CALL);
853 if (vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
854 in_snd_device = vc_usecase->in_snd_device;
855 out_snd_device = vc_usecase->out_snd_device;
856 }
857 }
858 if (usecase->type == PCM_PLAYBACK) {
859 usecase->devices = usecase->stream.out->devices;
860 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700861 if (out_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700862 out_snd_device = get_output_snd_device(adev,
863 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700864 if (usecase->stream.out == adev->primary_output &&
865 adev->active_input &&
866 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
867 select_devices(adev, adev->active_input->usecase);
868 }
869 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700870 } else if (usecase->type == PCM_CAPTURE) {
871 usecase->devices = usecase->stream.in->device;
872 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700873 if (in_snd_device == SND_DEVICE_NONE) {
874 if (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
875 adev->primary_output && !adev->primary_output->standby) {
876 in_snd_device = get_input_snd_device(adev,
877 adev->primary_output->devices);
878 } else {
879 in_snd_device = get_input_snd_device(adev, AUDIO_DEVICE_NONE);
880 }
881 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700882 }
883 }
884
885 if (out_snd_device == usecase->out_snd_device &&
886 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800887 return 0;
888 }
889
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800890 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
891 out_snd_device, device_table[out_snd_device],
892 in_snd_device, device_table[in_snd_device]);
893
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800894 /*
895 * Limitation: While in call, to do a device switch we need to disable
896 * and enable both RX and TX devices though one of them is same as current
897 * device.
898 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700899 if (usecase->type == VOICE_CALL && adev->csd_client != NULL &&
900 usecase->in_snd_device != SND_DEVICE_NONE &&
901 usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800902 /* This must be called before disabling the mixer controls on APQ side */
903 if (adev->csd_disable_device == NULL) {
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -0800904 ALOGE("%s: dlsym error for csd_client_disable_device", __func__);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800905 } else {
906 status = adev->csd_disable_device();
907 if (status < 0) {
908 ALOGE("%s: csd_client_disable_device, failed, error %d",
909 __func__, status);
910 }
911 }
912 }
913
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700914 /* Disable current sound devices */
915 if (usecase->out_snd_device != SND_DEVICE_NONE) {
916 disable_audio_route(adev, usecase, true);
917 disable_snd_device(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800918 }
919
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700920 if (usecase->in_snd_device != SND_DEVICE_NONE) {
921 disable_audio_route(adev, usecase, true);
922 disable_snd_device(adev, usecase->in_snd_device, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800923 }
924
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700925 /* Enable new sound devices */
926 if (out_snd_device != SND_DEVICE_NONE) {
927 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
928 check_usecases_codec_backend(adev, usecase, out_snd_device);
929 enable_snd_device(adev, out_snd_device, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800930 }
931
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700932 if (in_snd_device != SND_DEVICE_NONE)
933 enable_snd_device(adev, in_snd_device, false);
934
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800935 audio_route_update_mixer(adev->audio_route);
936
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700937 usecase->in_snd_device = in_snd_device;
938 usecase->out_snd_device = out_snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800939
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700940 enable_audio_route(adev, usecase, true);
941
942 if (usecase->type == VOICE_CALL && adev->csd_client) {
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800943 if (adev->csd_enable_device == NULL) {
944 ALOGE("%s: dlsym error for csd_client_enable_device",
945 __func__);
946 } else {
947 acdb_rx_id = get_acdb_device_id(out_snd_device);
948 acdb_tx_id = get_acdb_device_id(in_snd_device);
949
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700950 if (acdb_rx_id > 0 || acdb_tx_id > 0) {
951 status = adev->csd_enable_device(acdb_rx_id, acdb_tx_id,
952 adev->acdb_settings);
953 if (status < 0) {
954 ALOGE("%s: csd_client_enable_device, failed, error %d",
955 __func__, status);
956 }
957 } else {
958 ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__,
959 acdb_rx_id, acdb_tx_id);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800960 }
961 }
sangwoofbf5d512013-05-20 11:38:45 +0900962 } else if (usecase->type == VOICE_CALL) {
963 if (adev->acdb_send_voice_cal == NULL) {
964 ALOGE("%s: dlsym error for acdb_send_voice_call", __func__);
965 } else {
966 acdb_rx_id = get_acdb_device_id(out_snd_device);
967 acdb_tx_id = get_acdb_device_id(in_snd_device);
968
969 if (acdb_rx_id > 0 && acdb_tx_id > 0)
970 adev->acdb_send_voice_cal(acdb_rx_id, acdb_tx_id);
971 else
972 ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__,
973 acdb_rx_id, acdb_tx_id);
974 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800975 }
976
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800977 return status;
978}
979
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800980static int stop_input_stream(struct stream_in *in)
981{
982 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800983 struct audio_usecase *uc_info;
984 struct audio_device *adev = in->dev;
985
Eric Laurentc8400632013-02-14 19:04:54 -0800986 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800987
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700988 ALOGD("%s: enter: usecase(%d: %s)", __func__,
989 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800990 uc_info = get_usecase_from_list(adev, in->usecase);
991 if (uc_info == NULL) {
992 ALOGE("%s: Could not find the usecase (%d) in the list",
993 __func__, in->usecase);
994 return -EINVAL;
995 }
996
Eric Laurent150dbfe2013-02-27 14:31:02 -0800997 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700998 disable_audio_route(adev, uc_info, true);
999
1000 /* 2. Disable the tx device */
1001 disable_snd_device(adev, uc_info->in_snd_device, true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001002
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001003 list_remove(&uc_info->list);
1004 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001005
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001006 ALOGD("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001007 return ret;
1008}
1009
1010int start_input_stream(struct stream_in *in)
1011{
1012 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001013 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001014 struct audio_usecase *uc_info;
1015 struct audio_device *adev = in->dev;
1016
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001017 ALOGD("%s: enter: usecase(%d)", __func__, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001018 in->pcm_device_id = get_pcm_device_id(adev->audio_route,
1019 in->usecase,
1020 PCM_CAPTURE);
1021 if (in->pcm_device_id < 0) {
1022 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1023 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001024 ret = -EINVAL;
1025 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001026 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001027
1028 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001029 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1030 uc_info->id = in->usecase;
1031 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001032 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001033 uc_info->devices = in->device;
1034 uc_info->in_snd_device = SND_DEVICE_NONE;
1035 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001036
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001037 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001038 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001039
Eric Laurentc8400632013-02-14 19:04:54 -08001040 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1041 __func__, SOUND_CARD, in->pcm_device_id, in->config.channels);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001042 in->pcm = pcm_open(SOUND_CARD, in->pcm_device_id,
1043 PCM_IN, &in->config);
1044 if (in->pcm && !pcm_is_ready(in->pcm)) {
1045 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1046 pcm_close(in->pcm);
1047 in->pcm = NULL;
Eric Laurentc8400632013-02-14 19:04:54 -08001048 ret = -EIO;
1049 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001050 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001051 ALOGD("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001052 return ret;
1053
1054error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001055 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001056
1057error_config:
1058 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001059 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001060
1061 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001062}
1063
1064static int stop_output_stream(struct stream_out *out)
1065{
1066 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001067 struct audio_usecase *uc_info;
1068 struct audio_device *adev = out->dev;
1069
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001070 ALOGD("%s: enter: usecase(%d: %s)", __func__,
1071 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001072 uc_info = get_usecase_from_list(adev, out->usecase);
1073 if (uc_info == NULL) {
1074 ALOGE("%s: Could not find the usecase (%d) in the list",
1075 __func__, out->usecase);
1076 return -EINVAL;
1077 }
1078
Eric Laurent150dbfe2013-02-27 14:31:02 -08001079 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001080 disable_audio_route(adev, uc_info, true);
1081
1082 /* 2. Disable the rx device */
1083 disable_snd_device(adev, uc_info->out_snd_device, true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001084
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001085 list_remove(&uc_info->list);
1086 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001087
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001088 ALOGD("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001089 return ret;
1090}
1091
1092int start_output_stream(struct stream_out *out)
1093{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001094 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001095 struct audio_usecase *uc_info;
1096 struct audio_device *adev = out->dev;
1097
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001098 ALOGD("%s: enter: usecase(%d: %s) devices(%#x)",
1099 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001100 out->pcm_device_id = get_pcm_device_id(adev->audio_route,
1101 out->usecase,
1102 PCM_PLAYBACK);
1103 if (out->pcm_device_id < 0) {
1104 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1105 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001106 ret = -EINVAL;
1107 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001108 }
1109
1110 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1111 uc_info->id = out->usecase;
1112 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001113 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001114 uc_info->devices = out->devices;
1115 uc_info->in_snd_device = SND_DEVICE_NONE;
1116 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001117
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001118 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001119
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001120 select_devices(adev, out->usecase);
1121
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001122 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d)",
1123 __func__, 0, out->pcm_device_id);
1124 out->pcm = pcm_open(SOUND_CARD, out->pcm_device_id,
1125 PCM_OUT, &out->config);
1126 if (out->pcm && !pcm_is_ready(out->pcm)) {
1127 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1128 pcm_close(out->pcm);
1129 out->pcm = NULL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001130 ret = -EIO;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001131 goto error_pcm_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001132 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001133 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001134 return 0;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001135error_pcm_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001136 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001137error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001138 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001139}
1140
1141static int stop_voice_call(struct audio_device *adev)
1142{
1143 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001144 struct audio_usecase *uc_info;
1145
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001146 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -08001147 adev->in_call = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001148 if (adev->csd_client) {
1149 if (adev->csd_stop_voice == NULL) {
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001150 ALOGE("dlsym error for csd_client_disable_device");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001151 } else {
1152 ret = adev->csd_stop_voice();
1153 if (ret < 0) {
1154 ALOGE("%s: csd_client error %d\n", __func__, ret);
1155 }
1156 }
1157 }
1158
1159 /* 1. Close the PCM devices */
1160 if (adev->voice_call_rx) {
1161 pcm_close(adev->voice_call_rx);
1162 adev->voice_call_rx = NULL;
1163 }
1164 if (adev->voice_call_tx) {
1165 pcm_close(adev->voice_call_tx);
1166 adev->voice_call_tx = NULL;
1167 }
1168
1169 uc_info = get_usecase_from_list(adev, USECASE_VOICE_CALL);
1170 if (uc_info == NULL) {
1171 ALOGE("%s: Could not find the usecase (%d) in the list",
1172 __func__, USECASE_VOICE_CALL);
1173 return -EINVAL;
1174 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001175
1176 /* 2. Get and set stream specific mixer controls */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001177 disable_audio_route(adev, uc_info, true);
1178
1179 /* 3. Disable the rx and tx devices */
1180 disable_snd_device(adev, uc_info->out_snd_device, false);
1181 disable_snd_device(adev, uc_info->in_snd_device, true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001182
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001183 list_remove(&uc_info->list);
1184 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001185
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001186 ALOGD("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001187 return ret;
1188}
1189
1190static int start_voice_call(struct audio_device *adev)
1191{
1192 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001193 struct audio_usecase *uc_info;
1194 int pcm_dev_rx_id, pcm_dev_tx_id;
1195
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001196 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001197
1198 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1199 uc_info->id = USECASE_VOICE_CALL;
1200 uc_info->type = VOICE_CALL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001201 uc_info->stream.out = adev->primary_output;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001202 uc_info->devices = adev->primary_output->devices;
1203 uc_info->in_snd_device = SND_DEVICE_NONE;
1204 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001205
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001206 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001207
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001208 select_devices(adev, USECASE_VOICE_CALL);
1209
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001210 pcm_dev_rx_id = get_pcm_device_id(adev->audio_route, uc_info->id,
1211 PCM_PLAYBACK);
1212 pcm_dev_tx_id = get_pcm_device_id(adev->audio_route, uc_info->id,
1213 PCM_CAPTURE);
1214
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001215 if (pcm_dev_rx_id < 0 || pcm_dev_tx_id < 0) {
1216 ALOGE("%s: Invalid PCM devices (rx: %d tx: %d) for the usecase(%d)",
1217 __func__, pcm_dev_rx_id, pcm_dev_tx_id, uc_info->id);
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -08001218 ret = -EIO;
1219 goto error_start_voice;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001220 }
1221
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -08001222 ALOGV("%s: Opening PCM playback device card_id(%d) device_id(%d)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001223 __func__, SOUND_CARD, pcm_dev_rx_id);
1224 adev->voice_call_rx = pcm_open(SOUND_CARD,
1225 pcm_dev_rx_id,
1226 PCM_OUT, &pcm_config_voice_call);
1227 if (adev->voice_call_rx && !pcm_is_ready(adev->voice_call_rx)) {
1228 ALOGE("%s: %s", __func__, pcm_get_error(adev->voice_call_rx));
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -08001229 ret = -EIO;
1230 goto error_start_voice;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001231 }
1232
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -08001233 ALOGV("%s: Opening PCM capture device card_id(%d) device_id(%d)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001234 __func__, SOUND_CARD, pcm_dev_tx_id);
1235 adev->voice_call_tx = pcm_open(SOUND_CARD,
1236 pcm_dev_tx_id,
1237 PCM_IN, &pcm_config_voice_call);
1238 if (adev->voice_call_tx && !pcm_is_ready(adev->voice_call_tx)) {
1239 ALOGE("%s: %s", __func__, pcm_get_error(adev->voice_call_tx));
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -08001240 ret = -EIO;
1241 goto error_start_voice;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001242 }
1243 pcm_start(adev->voice_call_rx);
1244 pcm_start(adev->voice_call_tx);
1245
1246 if (adev->csd_client) {
1247 if (adev->csd_start_voice == NULL) {
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001248 ALOGE("dlsym error for csd_client_start_voice");
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -08001249 goto error_start_voice;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001250 } else {
1251 ret = adev->csd_start_voice();
1252 if (ret < 0) {
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -08001253 ALOGE("%s: csd_start_voice error %d\n", __func__, ret);
1254 goto error_start_voice;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001255 }
1256 }
1257 }
1258
1259 adev->in_call = true;
Ravi Kumar Alamanda8b9c5c82013-02-20 16:59:34 -08001260 return 0;
1261
1262error_start_voice:
1263 stop_voice_call(adev);
1264
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001265 ALOGD("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001266 return ret;
1267}
1268
1269static int check_input_parameters(uint32_t sample_rate,
1270 audio_format_t format,
1271 int channel_count)
1272{
1273 if (format != AUDIO_FORMAT_PCM_16_BIT) return -EINVAL;
1274
1275 if ((channel_count < 1) || (channel_count > 2)) return -EINVAL;
1276
1277 switch (sample_rate) {
1278 case 8000:
1279 case 11025:
1280 case 12000:
1281 case 16000:
1282 case 22050:
1283 case 24000:
1284 case 32000:
1285 case 44100:
1286 case 48000:
1287 break;
1288 default:
1289 return -EINVAL;
1290 }
1291
1292 return 0;
1293}
1294
1295static size_t get_input_buffer_size(uint32_t sample_rate,
1296 audio_format_t format,
1297 int channel_count)
1298{
1299 size_t size = 0;
1300
1301 if (check_input_parameters(sample_rate, format, channel_count) != 0) return 0;
1302
1303 if (sample_rate == 8000 || sample_rate == 16000 || sample_rate == 32000) {
1304 size = (sample_rate * 20) / 1000;
1305 } else if (sample_rate == 11025 || sample_rate == 12000) {
1306 size = 256;
1307 } else if (sample_rate == 22050 || sample_rate == 24000) {
1308 size = 512;
1309 } else if (sample_rate == 44100 || sample_rate == 48000) {
1310 size = 1024;
1311 }
1312
1313 return size * sizeof(short) * channel_count;
1314}
1315
1316static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1317{
1318 struct stream_out *out = (struct stream_out *)stream;
1319
1320 return out->config.rate;
1321}
1322
1323static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
1324{
1325 return -ENOSYS;
1326}
1327
1328static size_t out_get_buffer_size(const struct audio_stream *stream)
1329{
1330 struct stream_out *out = (struct stream_out *)stream;
1331
1332 return out->config.period_size * audio_stream_frame_size(stream);
1333}
1334
1335static uint32_t out_get_channels(const struct audio_stream *stream)
1336{
1337 struct stream_out *out = (struct stream_out *)stream;
1338
1339 return out->channel_mask;
1340}
1341
1342static audio_format_t out_get_format(const struct audio_stream *stream)
1343{
1344 return AUDIO_FORMAT_PCM_16_BIT;
1345}
1346
1347static int out_set_format(struct audio_stream *stream, audio_format_t format)
1348{
1349 return -ENOSYS;
1350}
1351
1352static int out_standby(struct audio_stream *stream)
1353{
1354 struct stream_out *out = (struct stream_out *)stream;
1355 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001356 ALOGD("%s: enter: usecase(%d: %s)", __func__,
1357 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001358 pthread_mutex_lock(&out->lock);
1359
1360 if (!out->standby) {
1361 out->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08001362 if (out->pcm) {
1363 pcm_close(out->pcm);
1364 out->pcm = NULL;
1365 }
1366 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001367 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001368 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001369 }
1370 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001371 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001372 return 0;
1373}
1374
1375static int out_dump(const struct audio_stream *stream, int fd)
1376{
1377 return 0;
1378}
1379
1380static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1381{
1382 struct stream_out *out = (struct stream_out *)stream;
1383 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001384 struct audio_usecase *usecase;
1385 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001386 struct str_parms *parms;
1387 char value[32];
1388 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001389 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001390
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001391 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
1392 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001393 parms = str_parms_create_str(kvpairs);
1394 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1395 if (ret >= 0) {
1396 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001397 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001398 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001399
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001400 /*
1401 * When HDMI cable is unplugged the music playback is paused and
1402 * the policy manager sends routing=0. But the audioflinger
1403 * continues to write data until standby time (3sec).
1404 * As the HDMI core is turned off, the write gets blocked.
1405 * Avoid this by routing audio to speaker until standby.
1406 */
1407 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
1408 val == AUDIO_DEVICE_NONE) {
1409 val = AUDIO_DEVICE_OUT_SPEAKER;
1410 }
1411
1412 /*
1413 * select_devices() call below switches all the usecases on the same
1414 * backend to the new device. Refer to check_usecases_codec_backend() in
1415 * the select_devices(). But how do we undo this?
1416 *
1417 * For example, music playback is active on headset (deep-buffer usecase)
1418 * and if we go to ringtones and select a ringtone, low-latency usecase
1419 * will be started on headset+speaker. As we can't enable headset+speaker
1420 * and headset devices at the same time, select_devices() switches the music
1421 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1422 * So when the ringtone playback is completed, how do we undo the same?
1423 *
1424 * We are relying on the out_set_parameters() call on deep-buffer output,
1425 * once the ringtone playback is ended.
1426 * NOTE: We should not check if the current devices are same as new devices.
1427 * Because select_devices() must be called to switch back the music
1428 * playback to headset.
1429 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001430 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001431 out->devices = val;
1432
1433 if (!out->standby)
1434 select_devices(adev, out->usecase);
1435
1436 if ((adev->mode == AUDIO_MODE_IN_CALL) && !adev->in_call &&
1437 (out == adev->primary_output)) {
1438 start_voice_call(adev);
1439 } else if ((adev->mode == AUDIO_MODE_IN_CALL) && adev->in_call &&
1440 (out == adev->primary_output)) {
1441 select_devices(adev, USECASE_VOICE_CALL);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001442 }
1443 }
1444
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001445 if ((adev->mode != AUDIO_MODE_IN_CALL) && adev->in_call &&
1446 (out == adev->primary_output)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001447 stop_voice_call(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001448 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001449
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001450 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001451 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001452 }
1453 str_parms_destroy(parms);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001454 ALOGD("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001455 return ret;
1456}
1457
1458static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1459{
1460 struct stream_out *out = (struct stream_out *)stream;
1461 struct str_parms *query = str_parms_create_str(keys);
1462 char *str;
1463 char value[256];
1464 struct str_parms *reply = str_parms_create();
1465 size_t i, j;
1466 int ret;
1467 bool first = true;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001468 ALOGD("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001469 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1470 if (ret >= 0) {
1471 value[0] = '\0';
1472 i = 0;
1473 while (out->supported_channel_masks[i] != 0) {
1474 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1475 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1476 if (!first) {
1477 strcat(value, "|");
1478 }
1479 strcat(value, out_channels_name_to_enum_table[j].name);
1480 first = false;
1481 break;
1482 }
1483 }
1484 i++;
1485 }
1486 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1487 str = str_parms_to_str(reply);
1488 } else {
1489 str = strdup(keys);
1490 }
1491 str_parms_destroy(query);
1492 str_parms_destroy(reply);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001493 ALOGD("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001494 return str;
1495}
1496
1497static uint32_t out_get_latency(const struct audio_stream_out *stream)
1498{
1499 struct stream_out *out = (struct stream_out *)stream;
1500
1501 return (out->config.period_count * out->config.period_size * 1000) / (out->config.rate);
1502}
1503
1504static int out_set_volume(struct audio_stream_out *stream, float left,
1505 float right)
1506{
Eric Laurenta9024de2013-04-04 09:19:12 -07001507 struct stream_out *out = (struct stream_out *)stream;
1508 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1509 /* only take left channel into account: the API is for stereo anyway */
1510 out->muted = (left == 0.0f);
1511 return 0;
1512 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001513 return -ENOSYS;
1514}
1515
1516static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
1517 size_t bytes)
1518{
1519 struct stream_out *out = (struct stream_out *)stream;
1520 struct audio_device *adev = out->dev;
1521 int i, ret = -1;
1522
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001523 pthread_mutex_lock(&out->lock);
1524 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001525 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08001526 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001527 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001528 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001529 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001530 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001531 goto exit;
1532 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001533 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001534
1535 if (out->pcm) {
Eric Laurenta9024de2013-04-04 09:19:12 -07001536 if (out->muted)
1537 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001538 //ALOGV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
1539 ret = pcm_write(out->pcm, (void *)buffer, bytes);
1540 }
1541
1542exit:
1543 pthread_mutex_unlock(&out->lock);
1544
1545 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001546 if (out->pcm)
1547 ALOGE("%s: error %d - %s", __func__, ret, pcm_get_error(out->pcm));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001548 out_standby(&out->stream.common);
1549 usleep(bytes * 1000000 / audio_stream_frame_size(&out->stream.common) /
1550 out_get_sample_rate(&out->stream.common));
1551 }
1552 return bytes;
1553}
1554
1555static int out_get_render_position(const struct audio_stream_out *stream,
1556 uint32_t *dsp_frames)
1557{
1558 return -EINVAL;
1559}
1560
1561static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1562{
1563 return 0;
1564}
1565
1566static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1567{
1568 return 0;
1569}
1570
1571static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
1572 int64_t *timestamp)
1573{
1574 return -EINVAL;
1575}
1576
1577/** audio_stream_in implementation **/
1578static uint32_t in_get_sample_rate(const struct audio_stream *stream)
1579{
1580 struct stream_in *in = (struct stream_in *)stream;
1581
1582 return in->config.rate;
1583}
1584
1585static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
1586{
1587 return -ENOSYS;
1588}
1589
1590static size_t in_get_buffer_size(const struct audio_stream *stream)
1591{
1592 struct stream_in *in = (struct stream_in *)stream;
1593
1594 return in->config.period_size * audio_stream_frame_size(stream);
1595}
1596
1597static uint32_t in_get_channels(const struct audio_stream *stream)
1598{
1599 struct stream_in *in = (struct stream_in *)stream;
1600
1601 return in->channel_mask;
1602}
1603
1604static audio_format_t in_get_format(const struct audio_stream *stream)
1605{
1606 return AUDIO_FORMAT_PCM_16_BIT;
1607}
1608
1609static int in_set_format(struct audio_stream *stream, audio_format_t format)
1610{
1611 return -ENOSYS;
1612}
1613
1614static int in_standby(struct audio_stream *stream)
1615{
1616 struct stream_in *in = (struct stream_in *)stream;
1617 struct audio_device *adev = in->dev;
1618 int status = 0;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001619 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001620 pthread_mutex_lock(&in->lock);
1621 if (!in->standby) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001622 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08001623 if (in->pcm) {
1624 pcm_close(in->pcm);
1625 in->pcm = NULL;
1626 }
1627 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001628 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001629 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001630 }
1631 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001632 ALOGD("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001633 return status;
1634}
1635
1636static int in_dump(const struct audio_stream *stream, int fd)
1637{
1638 return 0;
1639}
1640
1641static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
1642{
1643 struct stream_in *in = (struct stream_in *)stream;
1644 struct audio_device *adev = in->dev;
1645 struct str_parms *parms;
1646 char *str;
1647 char value[32];
1648 int ret, val = 0;
1649
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001650 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001651 parms = str_parms_create_str(kvpairs);
1652
1653 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
1654
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001655 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001656 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001657 if (ret >= 0) {
1658 val = atoi(value);
1659 /* no audio source uses val == 0 */
1660 if ((in->source != val) && (val != 0)) {
1661 in->source = val;
1662 }
1663 }
1664
1665 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1666 if (ret >= 0) {
1667 val = atoi(value);
1668 if ((in->device != val) && (val != 0)) {
1669 in->device = val;
1670 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001671 if (!in->standby)
1672 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001673 }
1674 }
1675
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001676 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001677 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001678
1679 str_parms_destroy(parms);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001680 ALOGD("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001681 return ret;
1682}
1683
1684static char* in_get_parameters(const struct audio_stream *stream,
1685 const char *keys)
1686{
1687 return strdup("");
1688}
1689
1690static int in_set_gain(struct audio_stream_in *stream, float gain)
1691{
1692 return 0;
1693}
1694
1695static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
1696 size_t bytes)
1697{
1698 struct stream_in *in = (struct stream_in *)stream;
1699 struct audio_device *adev = in->dev;
1700 int i, ret = -1;
1701
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001702 pthread_mutex_lock(&in->lock);
1703 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001704 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001705 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001706 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001707 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001708 goto exit;
1709 }
1710 in->standby = 0;
1711 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001712
1713 if (in->pcm) {
1714 ret = pcm_read(in->pcm, buffer, bytes);
1715 }
1716
1717 /*
1718 * Instead of writing zeroes here, we could trust the hardware
1719 * to always provide zeroes when muted.
1720 */
1721 if (ret == 0 && adev->mic_mute)
1722 memset(buffer, 0, bytes);
1723
1724exit:
1725 pthread_mutex_unlock(&in->lock);
1726
1727 if (ret != 0) {
1728 in_standby(&in->stream.common);
1729 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
1730 usleep(bytes * 1000000 / audio_stream_frame_size(&in->stream.common) /
1731 in_get_sample_rate(&in->stream.common));
1732 }
1733 return bytes;
1734}
1735
1736static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
1737{
1738 return 0;
1739}
1740
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001741static int add_remove_audio_effect(const struct audio_stream *stream,
1742 effect_handle_t effect,
1743 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001744{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001745 struct stream_in *in = (struct stream_in *)stream;
1746 int status = 0;
1747 effect_descriptor_t desc;
1748
1749 status = (*effect)->get_descriptor(effect, &desc);
1750 if (status != 0)
1751 return status;
1752
1753 pthread_mutex_lock(&in->lock);
1754 pthread_mutex_lock(&in->dev->lock);
1755 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
1756 in->enable_aec != enable &&
1757 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
1758 in->enable_aec = enable;
1759 if (!in->standby)
1760 select_devices(in->dev, in->usecase);
1761 }
1762 pthread_mutex_unlock(&in->dev->lock);
1763 pthread_mutex_unlock(&in->lock);
1764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001765 return 0;
1766}
1767
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001768static int in_add_audio_effect(const struct audio_stream *stream,
1769 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001770{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001771 ALOGD("%s: effect %p", __func__, effect);
1772 return add_remove_audio_effect(stream, effect, true);
1773}
1774
1775static int in_remove_audio_effect(const struct audio_stream *stream,
1776 effect_handle_t effect)
1777{
1778 ALOGD("%s: effect %p", __func__, effect);
1779 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001780}
1781
1782static int adev_open_output_stream(struct audio_hw_device *dev,
1783 audio_io_handle_t handle,
1784 audio_devices_t devices,
1785 audio_output_flags_t flags,
1786 struct audio_config *config,
1787 struct audio_stream_out **stream_out)
1788{
1789 struct audio_device *adev = (struct audio_device *)dev;
1790 struct stream_out *out;
1791 int i, ret;
1792
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001793 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001794 __func__, config->sample_rate, config->channel_mask, devices, flags);
1795 *stream_out = NULL;
1796 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
1797
1798 if (devices == AUDIO_DEVICE_NONE)
1799 devices = AUDIO_DEVICE_OUT_SPEAKER;
1800
1801 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
1802 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
1803 out->flags = flags;
1804 out->devices = devices;
1805
1806 /* Init use case and pcm_config */
1807 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
1808 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001809 pthread_mutex_lock(&adev->lock);
1810 ret = read_hdmi_channel_masks(out);
1811 pthread_mutex_unlock(&adev->lock);
1812 if (ret != 0) {
1813 /* If HDMI does not support multi channel playback, set the default */
1814 out->config.channels = popcount(out->channel_mask);
1815 set_hdmi_channels(adev->mixer, out->config.channels);
1816 goto error_open;
1817 }
1818
1819 if (config->sample_rate == 0)
1820 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1821 if (config->channel_mask == 0)
1822 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
1823
1824 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001825 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
1826 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001827 out->config.rate = config->sample_rate;
1828 out->config.channels = popcount(out->channel_mask);
1829 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
1830 set_hdmi_channels(adev->mixer, out->config.channels);
1831 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
1832 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
1833 out->config = pcm_config_deep_buffer;
1834 } else {
1835 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
1836 out->config = pcm_config_low_latency;
1837 }
1838
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001839 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
1840 if(adev->primary_output == NULL)
1841 adev->primary_output = out;
1842 else {
1843 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001844 ret = -EEXIST;
1845 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001846 }
1847 }
1848
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001849 /* Check if this usecase is already existing */
1850 pthread_mutex_lock(&adev->lock);
1851 if (get_usecase_from_list(adev, out->usecase) != NULL) {
1852 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001853 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001854 ret = -EEXIST;
1855 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001856 }
1857 pthread_mutex_unlock(&adev->lock);
1858
1859 out->stream.common.get_sample_rate = out_get_sample_rate;
1860 out->stream.common.set_sample_rate = out_set_sample_rate;
1861 out->stream.common.get_buffer_size = out_get_buffer_size;
1862 out->stream.common.get_channels = out_get_channels;
1863 out->stream.common.get_format = out_get_format;
1864 out->stream.common.set_format = out_set_format;
1865 out->stream.common.standby = out_standby;
1866 out->stream.common.dump = out_dump;
1867 out->stream.common.set_parameters = out_set_parameters;
1868 out->stream.common.get_parameters = out_get_parameters;
1869 out->stream.common.add_audio_effect = out_add_audio_effect;
1870 out->stream.common.remove_audio_effect = out_remove_audio_effect;
1871 out->stream.get_latency = out_get_latency;
1872 out->stream.set_volume = out_set_volume;
1873 out->stream.write = out_write;
1874 out->stream.get_render_position = out_get_render_position;
1875 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
1876
1877 out->dev = adev;
1878 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07001879 /* out->muted = false; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001880
1881 config->format = out->stream.common.get_format(&out->stream.common);
1882 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
1883 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
1884
1885 *stream_out = &out->stream;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001886 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001887 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001888
1889error_open:
1890 free(out);
1891 *stream_out = NULL;
1892 ALOGD("%s: exit: ret %d", __func__, ret);
1893 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001894}
1895
1896static void adev_close_output_stream(struct audio_hw_device *dev,
1897 struct audio_stream_out *stream)
1898{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001899 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001900 out_standby(&stream->common);
1901 free(stream);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001902 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001903}
1904
1905static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
1906{
1907 struct audio_device *adev = (struct audio_device *)dev;
1908 struct str_parms *parms;
1909 char *str;
1910 char value[32];
1911 int ret;
1912
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001913 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001914
1915 parms = str_parms_create_str(kvpairs);
1916 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_TTY_MODE, value, sizeof(value));
1917 if (ret >= 0) {
1918 int tty_mode;
1919
1920 if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_OFF) == 0)
1921 tty_mode = TTY_MODE_OFF;
1922 else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_VCO) == 0)
1923 tty_mode = TTY_MODE_VCO;
1924 else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_HCO) == 0)
1925 tty_mode = TTY_MODE_HCO;
1926 else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_FULL) == 0)
1927 tty_mode = TTY_MODE_FULL;
1928 else
1929 return -EINVAL;
1930
1931 pthread_mutex_lock(&adev->lock);
1932 if (tty_mode != adev->tty_mode) {
1933 adev->tty_mode = tty_mode;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08001934 adev->acdb_settings = (adev->acdb_settings & TTY_MODE_CLEAR) | tty_mode;
1935 if (adev->in_call)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001936 select_devices(adev, USECASE_VOICE_CALL);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001937 }
1938 pthread_mutex_unlock(&adev->lock);
1939 }
1940
1941 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
1942 if (ret >= 0) {
1943 /* When set to false, HAL should disable EC and NS
1944 * But it is currently not supported.
1945 */
1946 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
1947 adev->bluetooth_nrec = true;
1948 else
1949 adev->bluetooth_nrec = false;
1950 }
1951
1952 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
1953 if (ret >= 0) {
1954 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
1955 adev->screen_off = false;
1956 else
1957 adev->screen_off = true;
1958 }
1959
1960 str_parms_destroy(parms);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001961 ALOGD("%s: exit with code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001962 return ret;
1963}
1964
1965static char* adev_get_parameters(const struct audio_hw_device *dev,
1966 const char *keys)
1967{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001968 return strdup("");
1969}
1970
1971static int adev_init_check(const struct audio_hw_device *dev)
1972{
1973 return 0;
1974}
1975
1976static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
1977{
1978 struct audio_device *adev = (struct audio_device *)dev;
1979 int vol, err = 0;
1980
1981 pthread_mutex_lock(&adev->lock);
1982 adev->voice_volume = volume;
1983 if (adev->mode == AUDIO_MODE_IN_CALL) {
1984 if (volume < 0.0) {
1985 volume = 0.0;
1986 } else if (volume > 1.0) {
1987 volume = 1.0;
1988 }
1989
1990 vol = lrint(volume * 100.0);
1991
1992 // Voice volume levels from android are mapped to driver volume levels as follows.
1993 // 0 -> 5, 20 -> 4, 40 ->3, 60 -> 2, 80 -> 1, 100 -> 0
1994 // So adjust the volume to get the correct volume index in driver
1995 vol = 100 - vol;
Ravi Kumar Alamanda87f6ee02013-05-07 14:20:11 -07001996#ifdef MSM8974
1997 set_voice_volume(adev->mixer, vol);
1998#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001999 if (adev->csd_client) {
2000 if (adev->csd_volume == NULL) {
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002001 ALOGE("%s: dlsym error for csd_client_volume", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002002 } else {
2003 err = adev->csd_volume(vol);
2004 if (err < 0) {
2005 ALOGE("%s: csd_client error %d", __func__, err);
2006 }
2007 }
2008 } else {
2009 ALOGE("%s: No CSD Client present", __func__);
2010 }
Ravi Kumar Alamanda87f6ee02013-05-07 14:20:11 -07002011#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002012 }
2013 pthread_mutex_unlock(&adev->lock);
2014 return err;
2015}
2016
2017static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
2018{
2019 return -ENOSYS;
2020}
2021
2022static int adev_get_master_volume(struct audio_hw_device *dev,
2023 float *volume)
2024{
2025 return -ENOSYS;
2026}
2027
2028static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
2029{
2030 return -ENOSYS;
2031}
2032
2033static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
2034{
2035 return -ENOSYS;
2036}
2037
2038static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
2039{
2040 struct audio_device *adev = (struct audio_device *)dev;
2041
2042 pthread_mutex_lock(&adev->lock);
2043 if (adev->mode != mode) {
2044 adev->mode = mode;
2045 }
2046 pthread_mutex_unlock(&adev->lock);
2047 return 0;
2048}
2049
2050static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
2051{
2052 struct audio_device *adev = (struct audio_device *)dev;
2053 int err = 0;
2054
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002055 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002056 adev->mic_mute = state;
2057 if (adev->mode == AUDIO_MODE_IN_CALL) {
Ravi Kumar Alamanda87f6ee02013-05-07 14:20:11 -07002058#ifdef MSM8974
2059 set_mic_mute(adev->mixer, state);
2060#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002061 if (adev->csd_client) {
2062 if (adev->csd_mic_mute == NULL) {
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002063 ALOGE("%s: dlsym error for csd_mic_mute", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002064 } else {
2065 err = adev->csd_mic_mute(state);
2066 if (err < 0) {
2067 ALOGE("%s: csd_client error %d", __func__, err);
2068 }
2069 }
2070 } else {
2071 ALOGE("%s: No CSD Client present", __func__);
2072 }
Ravi Kumar Alamanda87f6ee02013-05-07 14:20:11 -07002073#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002074 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002075 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002076 return err;
2077}
2078
2079static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
2080{
2081 struct audio_device *adev = (struct audio_device *)dev;
2082
2083 *state = adev->mic_mute;
2084
2085 return 0;
2086}
2087
2088static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
2089 const struct audio_config *config)
2090{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002091 int channel_count = popcount(config->channel_mask);
2092
2093 return get_input_buffer_size(config->sample_rate, config->format, channel_count);
2094}
2095
2096static int adev_open_input_stream(struct audio_hw_device *dev,
2097 audio_io_handle_t handle,
2098 audio_devices_t devices,
2099 struct audio_config *config,
2100 struct audio_stream_in **stream_in)
2101{
2102 struct audio_device *adev = (struct audio_device *)dev;
2103 struct stream_in *in;
2104 int ret, buffer_size, frame_size;
2105 int channel_count = popcount(config->channel_mask);
2106
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002107 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002108 *stream_in = NULL;
2109 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
2110 return -EINVAL;
2111
2112 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
2113
2114 in->stream.common.get_sample_rate = in_get_sample_rate;
2115 in->stream.common.set_sample_rate = in_set_sample_rate;
2116 in->stream.common.get_buffer_size = in_get_buffer_size;
2117 in->stream.common.get_channels = in_get_channels;
2118 in->stream.common.get_format = in_get_format;
2119 in->stream.common.set_format = in_set_format;
2120 in->stream.common.standby = in_standby;
2121 in->stream.common.dump = in_dump;
2122 in->stream.common.set_parameters = in_set_parameters;
2123 in->stream.common.get_parameters = in_get_parameters;
2124 in->stream.common.add_audio_effect = in_add_audio_effect;
2125 in->stream.common.remove_audio_effect = in_remove_audio_effect;
2126 in->stream.set_gain = in_set_gain;
2127 in->stream.read = in_read;
2128 in->stream.get_input_frames_lost = in_get_input_frames_lost;
2129
2130 in->device = devices;
2131 in->source = AUDIO_SOURCE_DEFAULT;
2132 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002133 in->standby = 1;
2134 in->channel_mask = config->channel_mask;
2135
2136 /* Update config params with the requested sample rate and channels */
2137 in->usecase = USECASE_AUDIO_RECORD;
2138 in->config = pcm_config_audio_capture;
2139 in->config.channels = channel_count;
2140 in->config.rate = config->sample_rate;
2141
2142 frame_size = audio_stream_frame_size((struct audio_stream *)in);
2143 buffer_size = get_input_buffer_size(config->sample_rate,
2144 config->format,
2145 channel_count);
2146 in->config.period_size = buffer_size / frame_size;
2147
2148 *stream_in = &in->stream;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002149 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002150 return 0;
2151
2152err_open:
2153 free(in);
2154 *stream_in = NULL;
2155 return ret;
2156}
2157
2158static void adev_close_input_stream(struct audio_hw_device *dev,
2159 struct audio_stream_in *stream)
2160{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002161 ALOGD("%s", __func__);
2162
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002163 in_standby(&stream->common);
2164 free(stream);
2165
2166 return;
2167}
2168
2169static int adev_dump(const audio_hw_device_t *device, int fd)
2170{
2171 return 0;
2172}
2173
2174static int adev_close(hw_device_t *device)
2175{
2176 struct audio_device *adev = (struct audio_device *)device;
2177 audio_route_free(adev->audio_route);
2178 free(device);
2179 return 0;
2180}
2181
2182static void init_platform_data(struct audio_device *adev)
2183{
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -08002184 char platform[PROPERTY_VALUE_MAX];
2185 char baseband[PROPERTY_VALUE_MAX];
2186 char value[PROPERTY_VALUE_MAX];
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -08002187
2188 adev->dualmic_config = DUALMIC_CONFIG_NONE;
Ravi Kumar Alamanda02317792013-03-04 20:56:50 -08002189 adev->fluence_in_spkr_mode = false;
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -08002190 adev->fluence_in_voice_call = false;
2191 adev->fluence_in_voice_rec = false;
2192 adev->mic_type_analog = false;
2193
2194 property_get("persist.audio.handset.mic.type",value,"");
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002195 if (!strcmp("analog", value))
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -08002196 adev->mic_type_analog = true;
2197
2198 property_get("persist.audio.dualmic.config",value,"");
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002199 if (!strcmp("broadside", value)) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -08002200 adev->dualmic_config = DUALMIC_CONFIG_BROADSIDE;
2201 adev->acdb_settings |= DMIC_FLAG;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002202 } else if (!strcmp("endfire", value)) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -08002203 adev->dualmic_config = DUALMIC_CONFIG_ENDFIRE;
2204 adev->acdb_settings |= DMIC_FLAG;
2205 }
2206
2207 if (adev->dualmic_config != DUALMIC_CONFIG_NONE) {
2208 property_get("persist.audio.fluence.voicecall",value,"");
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002209 if (!strcmp("true", value)) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -08002210 adev->fluence_in_voice_call = true;
2211 }
2212
2213 property_get("persist.audio.fluence.voicerec",value,"");
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002214 if (!strcmp("true", value)) {
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -08002215 adev->fluence_in_voice_rec = true;
2216 }
Ravi Kumar Alamanda02317792013-03-04 20:56:50 -08002217
2218 property_get("persist.audio.fluence.speaker",value,"");
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002219 if (!strcmp("true", value)) {
Ravi Kumar Alamanda02317792013-03-04 20:56:50 -08002220 adev->fluence_in_spkr_mode = true;
2221 }
Ravi Kumar Alamanda72c411f2013-02-12 02:09:33 -08002222 }
2223
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002224 adev->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
2225 if (adev->acdb_handle == NULL) {
2226 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_ACDB_LOADER);
2227 } else {
2228 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_ACDB_LOADER);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002229 adev->acdb_deallocate = (acdb_deallocate_t)dlsym(adev->acdb_handle,
2230 "acdb_loader_deallocate_ACDB");
2231 adev->acdb_send_audio_cal = (acdb_send_audio_cal_t)dlsym(adev->acdb_handle,
2232 "acdb_loader_send_audio_cal");
2233 adev->acdb_send_voice_cal = (acdb_send_voice_cal_t)dlsym(adev->acdb_handle,
2234 "acdb_loader_send_voice_cal");
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002235 adev->acdb_init = (acdb_init_t)dlsym(adev->acdb_handle,
2236 "acdb_loader_init_ACDB");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002237 if (adev->acdb_init == NULL)
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002238 ALOGE("%s: dlsym error %s for acdb_loader_init_ACDB", __func__, dlerror());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002239 else
2240 adev->acdb_init();
2241 }
2242
2243 /* If platform is Fusion3, load CSD Client specific symbols
2244 * Voice call is handled by MDM and apps processor talks to
2245 * MDM through CSD Client
2246 */
2247 property_get("ro.board.platform", platform, "");
2248 property_get("ro.baseband", baseband, "");
2249 if (!strcmp("msm8960", platform) && !strcmp("mdm", baseband)) {
2250 adev->csd_client = dlopen(LIB_CSD_CLIENT, RTLD_NOW);
2251 if (adev->csd_client == NULL)
2252 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_CSD_CLIENT);
2253 }
2254
2255 if (adev->csd_client) {
2256 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_CSD_CLIENT);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002257 adev->csd_client_deinit = (csd_client_deinit_t)dlsym(adev->csd_client,
2258 "csd_client_deinit");
2259 adev->csd_disable_device = (csd_disable_device_t)dlsym(adev->csd_client,
2260 "csd_client_disable_device");
2261 adev->csd_enable_device = (csd_enable_device_t)dlsym(adev->csd_client,
2262 "csd_client_enable_device");
2263 adev->csd_start_voice = (csd_start_voice_t)dlsym(adev->csd_client,
2264 "csd_client_start_voice");
2265 adev->csd_stop_voice = (csd_stop_voice_t)dlsym(adev->csd_client,
2266 "csd_client_stop_voice");
2267 adev->csd_volume = (csd_volume_t)dlsym(adev->csd_client,
2268 "csd_client_volume");
2269 adev->csd_mic_mute = (csd_mic_mute_t)dlsym(adev->csd_client,
2270 "csd_client_mic_mute");
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002271 adev->csd_client_init = (csd_client_init_t)dlsym(adev->csd_client,
2272 "csd_client_init");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002273
2274 if (adev->csd_client_init == NULL) {
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002275 ALOGE("%s: dlsym error %s for csd_client_init", __func__, dlerror());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002276 } else {
2277 adev->csd_client_init();
2278 }
2279 }
2280}
2281
2282static int adev_open(const hw_module_t *module, const char *name,
2283 hw_device_t **device)
2284{
2285 struct audio_device *adev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002286 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002287
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002288 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002289 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
2290
2291 adev = calloc(1, sizeof(struct audio_device));
2292
2293 adev->mixer = mixer_open(MIXER_CARD);
2294 if (!adev->mixer) {
2295 ALOGE("Unable to open the mixer, aborting.");
2296 return -ENOSYS;
2297 }
2298
2299 adev->audio_route = audio_route_init(MIXER_CARD, MIXER_XML_PATH);
2300 if (!adev->audio_route) {
2301 free(adev);
2302 ALOGE("%s: Failed to init audio route controls, aborting.", __func__);
2303 *device = NULL;
2304 return -EINVAL;
2305 }
2306
2307 adev->device.common.tag = HARDWARE_DEVICE_TAG;
2308 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
2309 adev->device.common.module = (struct hw_module_t *)module;
2310 adev->device.common.close = adev_close;
2311
2312 adev->device.init_check = adev_init_check;
2313 adev->device.set_voice_volume = adev_set_voice_volume;
2314 adev->device.set_master_volume = adev_set_master_volume;
2315 adev->device.get_master_volume = adev_get_master_volume;
2316 adev->device.set_master_mute = adev_set_master_mute;
2317 adev->device.get_master_mute = adev_get_master_mute;
2318 adev->device.set_mode = adev_set_mode;
2319 adev->device.set_mic_mute = adev_set_mic_mute;
2320 adev->device.get_mic_mute = adev_get_mic_mute;
2321 adev->device.set_parameters = adev_set_parameters;
2322 adev->device.get_parameters = adev_get_parameters;
2323 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
2324 adev->device.open_output_stream = adev_open_output_stream;
2325 adev->device.close_output_stream = adev_close_output_stream;
2326 adev->device.open_input_stream = adev_open_input_stream;
2327 adev->device.close_input_stream = adev_close_input_stream;
2328 adev->device.dump = adev_dump;
2329
2330 /* Set the default route before the PCM stream is opened */
2331 pthread_mutex_lock(&adev->lock);
2332 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08002333 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002334 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002335 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002336 adev->voice_call_rx = NULL;
2337 adev->voice_call_tx = NULL;
2338 adev->voice_volume = 1.0f;
2339 adev->tty_mode = TTY_MODE_OFF;
2340 adev->bluetooth_nrec = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002341 adev->in_call = false;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08002342 adev->acdb_settings = TTY_MODE_OFF;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002343 for (i = 0; i < SND_DEVICE_MAX; i++) {
2344 adev->snd_dev_ref_cnt[i] = 0;
2345 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002346 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002347 pthread_mutex_unlock(&adev->lock);
2348
2349 /* Loads platform specific libraries dynamically */
2350 init_platform_data(adev);
2351
2352 *device = &adev->device.common;
2353
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002354 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002355 return 0;
2356}
2357
2358static struct hw_module_methods_t hal_module_methods = {
2359 .open = adev_open,
2360};
2361
2362struct audio_module HAL_MODULE_INFO_SYM = {
2363 .common = {
2364 .tag = HARDWARE_MODULE_TAG,
2365 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
2366 .hal_api_version = HARDWARE_HAL_API_VERSION,
2367 .id = AUDIO_HARDWARE_MODULE_ID,
2368 .name = "QCOM Audio HAL",
2369 .author = "Code Aurora Forum",
2370 .methods = &hal_module_methods,
2371 },
2372};