blob: f89439efdd310eb8ffcd32d0b09b70cb80f88380 [file] [log] [blame]
Eric Laurentb23d5282013-05-14 15:27:20 -07001/*
Eric Laurenta609e8e2014-06-18 02:15:17 +00002 * Copyright (C) 2013 The Android Open Source Project
Eric Laurentb23d5282013-05-14 15:27:20 -07003 *
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 "msm8974_platform"
18/*#define LOG_NDEBUG 0*/
19#define LOG_NDDEBUG 0
20
21#include <stdlib.h>
22#include <dlfcn.h>
23#include <cutils/log.h>
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -070024#include <cutils/str_parms.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070025#include <cutils/properties.h>
26#include <audio_hw.h>
27#include <platform_api.h>
28#include "platform.h"
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -070029#ifdef PLATFORM_MSM8084
30#include "mdm_detect.h"
31#endif
Eric Laurentb23d5282013-05-14 15:27:20 -070032
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -070033#define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
Eric Laurentb23d5282013-05-14 15:27:20 -070034#define LIB_ACDB_LOADER "libacdbloader.so"
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -070035#define AUDIO_DATA_BLOCK_MIXER_CTL "HDMI EDID"
Eric Laurentb23d5282013-05-14 15:27:20 -070036
37#define DUALMIC_CONFIG_NONE 0 /* Target does not contain 2 mics */
38#define DUALMIC_CONFIG_ENDFIRE 1
39#define DUALMIC_CONFIG_BROADSIDE 2
40
41/*
Eric Laurentb23d5282013-05-14 15:27:20 -070042 * This file will have a maximum of 38 bytes:
43 *
44 * 4 bytes: number of audio blocks
45 * 4 bytes: total length of Short Audio Descriptor (SAD) blocks
46 * Maximum 10 * 3 bytes: SAD blocks
47 */
48#define MAX_SAD_BLOCKS 10
49#define SAD_BLOCK_SIZE 3
50
51/* EDID format ID for LPCM audio */
52#define EDID_FORMAT_LPCM 1
53
sangwoo1b9f4b32013-06-21 18:22:55 -070054/* Retry for delay in FW loading*/
55#define RETRY_NUMBER 10
56#define RETRY_US 500000
Eric Laurenta609e8e2014-06-18 02:15:17 +000057
58#define MAX_VOL_INDEX 5
59#define MIN_VOL_INDEX 0
60#define percent_to_index(val, min, max) \
61 ((val) * ((max) - (min)) * 0.01 + (min) + .5)
sangwoo53b2cf02013-07-25 19:18:44 -070062
Eric Laurentb23d5282013-05-14 15:27:20 -070063struct audio_block_header
64{
65 int reserved;
66 int length;
67};
68
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -070069/* Audio calibration related functions */
Eric Laurentb23d5282013-05-14 15:27:20 -070070typedef void (*acdb_deallocate_t)();
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -070071#ifdef PLATFORM_MSM8084
72typedef int (*acdb_init_t)(char *);
73#else
Eric Laurentb23d5282013-05-14 15:27:20 -070074typedef int (*acdb_init_t)();
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -070075#endif
Eric Laurentb23d5282013-05-14 15:27:20 -070076typedef void (*acdb_send_audio_cal_t)(int, int);
77typedef void (*acdb_send_voice_cal_t)(int, int);
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -070078typedef int (*acdb_reload_vocvoltable_t)(int);
Eric Laurentb23d5282013-05-14 15:27:20 -070079
80/* Audio calibration related functions */
81struct platform_data {
82 struct audio_device *adev;
83 bool fluence_in_spkr_mode;
84 bool fluence_in_voice_call;
85 bool fluence_in_voice_rec;
86 int dualmic_config;
Eric Laurentb23d5282013-05-14 15:27:20 -070087 void *acdb_handle;
88 acdb_init_t acdb_init;
89 acdb_deallocate_t acdb_deallocate;
90 acdb_send_audio_cal_t acdb_send_audio_cal;
91 acdb_send_voice_cal_t acdb_send_voice_cal;
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -070092 acdb_reload_vocvoltable_t acdb_reload_vocvoltable;
93 struct csd_data *csd;
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -050094 bool ext_speaker;
95 bool ext_earpiece;
Eric Laurentb23d5282013-05-14 15:27:20 -070096};
97
98static const int pcm_device_table[AUDIO_USECASE_MAX][2] = {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -070099 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {DEEP_BUFFER_PCM_DEVICE,
100 DEEP_BUFFER_PCM_DEVICE},
101 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
102 LOWLATENCY_PCM_DEVICE},
103 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {MULTIMEDIA2_PCM_DEVICE,
104 MULTIMEDIA2_PCM_DEVICE},
105 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {PLAYBACK_OFFLOAD_DEVICE,
106 PLAYBACK_OFFLOAD_DEVICE},
107 [USECASE_AUDIO_RECORD] = {AUDIO_RECORD_PCM_DEVICE,
108 AUDIO_RECORD_PCM_DEVICE},
109 [USECASE_AUDIO_RECORD_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
110 LOWLATENCY_PCM_DEVICE},
111 [USECASE_VOICE_CALL] = {VOICE_CALL_PCM_DEVICE,
112 VOICE_CALL_PCM_DEVICE},
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800113 [USECASE_AUDIO_HFP_SCO] = {HFP_PCM_RX, HFP_SCO_RX},
Eric Laurentb23d5282013-05-14 15:27:20 -0700114};
115
116/* Array to store sound devices */
117static const char * const device_table[SND_DEVICE_MAX] = {
118 [SND_DEVICE_NONE] = "none",
119 /* Playback sound devices */
120 [SND_DEVICE_OUT_HANDSET] = "handset",
121 [SND_DEVICE_OUT_SPEAKER] = "speaker",
122 [SND_DEVICE_OUT_SPEAKER_REVERSE] = "speaker-reverse",
123 [SND_DEVICE_OUT_HEADPHONES] = "headphones",
124 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones",
125 [SND_DEVICE_OUT_VOICE_HANDSET] = "voice-handset",
126 [SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker",
127 [SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones",
128 [SND_DEVICE_OUT_HDMI] = "hdmi",
129 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
130 [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -0700131 [SND_DEVICE_OUT_BT_SCO_WB] = "bt-sco-headset-wb",
Eric Laurentb23d5282013-05-14 15:27:20 -0700132 [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = "voice-handset-tmus",
133 [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = "voice-tty-full-headphones",
134 [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = "voice-tty-vco-headphones",
135 [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = "voice-tty-hco-handset",
136
137 /* Capture sound devices */
138 [SND_DEVICE_IN_HANDSET_MIC] = "handset-mic",
139 [SND_DEVICE_IN_SPEAKER_MIC] = "speaker-mic",
140 [SND_DEVICE_IN_HEADSET_MIC] = "headset-mic",
141 [SND_DEVICE_IN_HANDSET_MIC_AEC] = "handset-mic",
Eric Laurent34fa7692014-03-07 09:31:06 -0800142 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = "speaker-mic-aec",
Eric Laurentb23d5282013-05-14 15:27:20 -0700143 [SND_DEVICE_IN_HEADSET_MIC_AEC] = "headset-mic",
144 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "voice-speaker-mic",
145 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "voice-headset-mic",
146 [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic",
147 [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic",
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -0700148 [SND_DEVICE_IN_BT_SCO_MIC_WB] = "bt-sco-mic-wb",
Eric Laurentb23d5282013-05-14 15:27:20 -0700149 [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic",
150 [SND_DEVICE_IN_VOICE_DMIC_EF] = "voice-dmic-ef",
151 [SND_DEVICE_IN_VOICE_DMIC_BS] = "voice-dmic-bs",
152 [SND_DEVICE_IN_VOICE_DMIC_EF_TMUS] = "voice-dmic-ef-tmus",
153 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF] = "voice-speaker-dmic-ef",
154 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS] = "voice-speaker-dmic-bs",
155 [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = "voice-tty-full-headset-mic",
156 [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = "voice-tty-vco-handset-mic",
157 [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = "voice-tty-hco-headset-mic",
158 [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic",
159 [SND_DEVICE_IN_VOICE_REC_DMIC_EF] = "voice-rec-dmic-ef",
160 [SND_DEVICE_IN_VOICE_REC_DMIC_BS] = "voice-rec-dmic-bs",
161 [SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE] = "voice-rec-dmic-ef-fluence",
162 [SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE] = "voice-rec-dmic-bs-fluence",
163};
164
165/* ACDB IDs (audio DSP path configuration IDs) for each sound device */
166static const int acdb_device_table[SND_DEVICE_MAX] = {
167 [SND_DEVICE_NONE] = -1,
168 [SND_DEVICE_OUT_HANDSET] = 7,
169 [SND_DEVICE_OUT_SPEAKER] = 15,
170 [SND_DEVICE_OUT_SPEAKER_REVERSE] = 15,
171 [SND_DEVICE_OUT_HEADPHONES] = 10,
172 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = 10,
173 [SND_DEVICE_OUT_VOICE_HANDSET] = 7,
174 [SND_DEVICE_OUT_VOICE_SPEAKER] = 15,
175 [SND_DEVICE_OUT_VOICE_HEADPHONES] = 10,
176 [SND_DEVICE_OUT_HDMI] = 18,
177 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 15,
178 [SND_DEVICE_OUT_BT_SCO] = 22,
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -0700179 [SND_DEVICE_OUT_BT_SCO_WB] = 39,
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700180 [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = ACDB_ID_VOICE_HANDSET_TMUS,
Eric Laurentb23d5282013-05-14 15:27:20 -0700181 [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = 17,
182 [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = 17,
183 [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = 37,
184
185 [SND_DEVICE_IN_HANDSET_MIC] = 4,
186 [SND_DEVICE_IN_SPEAKER_MIC] = 4, /* ToDo: Check if this needs to changed to 11 */
187 [SND_DEVICE_IN_HEADSET_MIC] = 8,
188 [SND_DEVICE_IN_HANDSET_MIC_AEC] = 40,
189 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = 42,
190 [SND_DEVICE_IN_HEADSET_MIC_AEC] = 47,
191 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = 11,
192 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = 8,
193 [SND_DEVICE_IN_HDMI_MIC] = 4,
194 [SND_DEVICE_IN_BT_SCO_MIC] = 21,
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -0700195 [SND_DEVICE_IN_BT_SCO_MIC_WB] = 38,
Eric Laurentb23d5282013-05-14 15:27:20 -0700196 [SND_DEVICE_IN_CAMCORDER_MIC] = 61,
197 [SND_DEVICE_IN_VOICE_DMIC_EF] = 41,
198 [SND_DEVICE_IN_VOICE_DMIC_BS] = 5,
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700199 [SND_DEVICE_IN_VOICE_DMIC_EF_TMUS] = ACDB_ID_VOICE_DMIC_EF_TMUS,
Eric Laurentb23d5282013-05-14 15:27:20 -0700200 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF] = 43,
201 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS] = 12,
202 [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = 16,
203 [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = 36,
204 [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = 16,
205 [SND_DEVICE_IN_VOICE_REC_MIC] = 62,
206 /* TODO: Update with proper acdb ids */
207 [SND_DEVICE_IN_VOICE_REC_DMIC_EF] = 62,
208 [SND_DEVICE_IN_VOICE_REC_DMIC_BS] = 62,
209 [SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE] = 6,
210 [SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE] = 5,
211};
212
Haynes Mathew George7ff216f2013-09-11 19:51:41 -0700213#define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL)
214#define LOW_LATENCY_PLATFORM_DELAY (13*1000LL)
215
Eric Laurentb23d5282013-05-14 15:27:20 -0700216static pthread_once_t check_op_once_ctl = PTHREAD_ONCE_INIT;
217static bool is_tmus = false;
218
219static void check_operator()
220{
221 char value[PROPERTY_VALUE_MAX];
222 int mccmnc;
223 property_get("gsm.sim.operator.numeric",value,"0");
224 mccmnc = atoi(value);
225 ALOGD("%s: tmus mccmnc %d", __func__, mccmnc);
226 switch(mccmnc) {
227 /* TMUS MCC(310), MNC(490, 260, 026) */
228 case 310490:
229 case 310260:
230 case 310026:
sangwon.jeonb891db52013-09-14 17:39:15 +0900231 /* Add new TMUS MNC(800, 660, 580, 310, 270, 250, 240, 230, 220, 210, 200, 160) */
232 case 310800:
233 case 310660:
234 case 310580:
235 case 310310:
236 case 310270:
237 case 310250:
238 case 310240:
239 case 310230:
240 case 310220:
241 case 310210:
242 case 310200:
243 case 310160:
Eric Laurentb23d5282013-05-14 15:27:20 -0700244 is_tmus = true;
245 break;
246 }
247}
248
249bool is_operator_tmus()
250{
251 pthread_once(&check_op_once_ctl, check_operator);
252 return is_tmus;
253}
254
Eric Laurenta609e8e2014-06-18 02:15:17 +0000255static int set_volume_values(int type, int volume, int* values)
256{
257 values[0] = volume;
258 values[1] = ALL_SESSION_VSID;
259
260 switch(type) {
261 case VOLUME_SET:
262 values[2] = DEFAULT_VOLUME_RAMP_DURATION_MS;
263 break;
264 case MUTE_SET:
265 values[2] = DEFAULT_MUTE_RAMP_DURATION;
266 break;
267 default:
268 return -EINVAL;
269 }
270 return 0;
271}
272
Eric Laurentb23d5282013-05-14 15:27:20 -0700273static int set_echo_reference(struct mixer *mixer, const char* ec_ref)
274{
275 struct mixer_ctl *ctl;
276 const char *mixer_ctl_name = "EC_REF_RX";
277
278 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
279 if (!ctl) {
280 ALOGE("%s: Could not get ctl for mixer cmd - %s",
281 __func__, mixer_ctl_name);
282 return -EINVAL;
283 }
284 ALOGV("Setting EC Reference: %s", ec_ref);
285 mixer_ctl_set_enum_by_string(ctl, ec_ref);
286 return 0;
287}
288
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700289static struct csd_data *open_csd_client(bool i2s_ext_modem)
290{
291 struct csd_data *csd = calloc(1, sizeof(struct csd_data));
292
293 csd->csd_client = dlopen(LIB_CSD_CLIENT, RTLD_NOW);
294 if (csd->csd_client == NULL) {
295 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_CSD_CLIENT);
296 goto error;
297 } else {
298 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_CSD_CLIENT);
299
300 csd->deinit = (deinit_t)dlsym(csd->csd_client,
301 "csd_client_deinit");
302 if (csd->deinit == NULL) {
303 ALOGE("%s: dlsym error %s for csd_client_deinit", __func__,
304 dlerror());
305 goto error;
306 }
307 csd->disable_device = (disable_device_t)dlsym(csd->csd_client,
308 "csd_client_disable_device");
309 if (csd->disable_device == NULL) {
310 ALOGE("%s: dlsym error %s for csd_client_disable_device",
311 __func__, dlerror());
312 goto error;
313 }
314 csd->enable_device_config = (enable_device_config_t)dlsym(csd->csd_client,
315 "csd_client_enable_device_config");
316 if (csd->enable_device_config == NULL) {
317 ALOGE("%s: dlsym error %s for csd_client_enable_device_config",
318 __func__, dlerror());
319 goto error;
320 }
321 csd->enable_device = (enable_device_t)dlsym(csd->csd_client,
322 "csd_client_enable_device");
323 if (csd->enable_device == NULL) {
324 ALOGE("%s: dlsym error %s for csd_client_enable_device",
325 __func__, dlerror());
326 goto error;
327 }
328 csd->start_voice = (start_voice_t)dlsym(csd->csd_client,
329 "csd_client_start_voice");
330 if (csd->start_voice == NULL) {
331 ALOGE("%s: dlsym error %s for csd_client_start_voice",
332 __func__, dlerror());
333 goto error;
334 }
335 csd->stop_voice = (stop_voice_t)dlsym(csd->csd_client,
336 "csd_client_stop_voice");
337 if (csd->stop_voice == NULL) {
338 ALOGE("%s: dlsym error %s for csd_client_stop_voice",
339 __func__, dlerror());
340 goto error;
341 }
342 csd->volume = (volume_t)dlsym(csd->csd_client,
343 "csd_client_volume");
344 if (csd->volume == NULL) {
345 ALOGE("%s: dlsym error %s for csd_client_volume",
346 __func__, dlerror());
347 goto error;
348 }
349 csd->mic_mute = (mic_mute_t)dlsym(csd->csd_client,
350 "csd_client_mic_mute");
351 if (csd->mic_mute == NULL) {
352 ALOGE("%s: dlsym error %s for csd_client_mic_mute",
353 __func__, dlerror());
354 goto error;
355 }
356 csd->slow_talk = (slow_talk_t)dlsym(csd->csd_client,
357 "csd_client_slow_talk");
358 if (csd->slow_talk == NULL) {
359 ALOGE("%s: dlsym error %s for csd_client_slow_talk",
360 __func__, dlerror());
361 goto error;
362 }
363 csd->start_playback = (start_playback_t)dlsym(csd->csd_client,
364 "csd_client_start_playback");
365 if (csd->start_playback == NULL) {
366 ALOGE("%s: dlsym error %s for csd_client_start_playback",
367 __func__, dlerror());
368 goto error;
369 }
370 csd->stop_playback = (stop_playback_t)dlsym(csd->csd_client,
371 "csd_client_stop_playback");
372 if (csd->stop_playback == NULL) {
373 ALOGE("%s: dlsym error %s for csd_client_stop_playback",
374 __func__, dlerror());
375 goto error;
376 }
377 csd->start_record = (start_record_t)dlsym(csd->csd_client,
378 "csd_client_start_record");
379 if (csd->start_record == NULL) {
380 ALOGE("%s: dlsym error %s for csd_client_start_record",
381 __func__, dlerror());
382 goto error;
383 }
384 csd->stop_record = (stop_record_t)dlsym(csd->csd_client,
385 "csd_client_stop_record");
386 if (csd->stop_record == NULL) {
387 ALOGE("%s: dlsym error %s for csd_client_stop_record",
388 __func__, dlerror());
389 goto error;
390 }
391
392 csd->get_sample_rate = (get_sample_rate_t)dlsym(csd->csd_client,
393 "csd_client_get_sample_rate");
394 if (csd->get_sample_rate == NULL) {
395 ALOGE("%s: dlsym error %s for csd_client_get_sample_rate",
396 __func__, dlerror());
397
398 goto error;
399 }
400
401 csd->init = (init_t)dlsym(csd->csd_client, "csd_client_init");
402
403 if (csd->init == NULL) {
404 ALOGE("%s: dlsym error %s for csd_client_init",
405 __func__, dlerror());
406 goto error;
407 } else {
408 csd->init(i2s_ext_modem);
409 }
410 }
411 return csd;
412
413error:
414 free(csd);
415 csd = NULL;
416 return csd;
417}
418
419void close_csd_client(struct csd_data *csd)
420{
421 if (csd != NULL) {
422 csd->deinit();
423 dlclose(csd->csd_client);
424 free(csd);
425 csd = NULL;
426 }
427}
428
429static void platform_csd_init(struct platform_data *my_data)
430{
431#ifdef PLATFORM_MSM8084
432 struct dev_info mdm_detect_info;
433 int ret = 0;
434
435 /* Call ESOC API to get the number of modems.
436 * If the number of modems is not zero, load CSD Client specific
437 * symbols. Voice call is handled by MDM and apps processor talks to
438 * MDM through CSD Client
439 */
440 ret = get_system_info(&mdm_detect_info);
441 if (ret > 0) {
442 ALOGE("%s: Failed to get system info, ret %d", __func__, ret);
443 }
444 ALOGD("%s: num_modems %d\n", __func__, mdm_detect_info.num_modems);
445
446 if (mdm_detect_info.num_modems > 0)
447 my_data->csd = open_csd_client(false /*is_i2s_ext_modem*/);
448#else
449 my_data->csd = NULL;
450#endif
451}
452
Eric Laurentb23d5282013-05-14 15:27:20 -0700453void *platform_init(struct audio_device *adev)
454{
455 char value[PROPERTY_VALUE_MAX];
456 struct platform_data *my_data;
Eric Laurenta609e8e2014-06-18 02:15:17 +0000457 int retry_num = 0;
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700458 const char *snd_card_name;
sangwoo1b9f4b32013-06-21 18:22:55 -0700459
Eric Laurenta609e8e2014-06-18 02:15:17 +0000460 adev->mixer = mixer_open(MIXER_CARD);
sangwoo1b9f4b32013-06-21 18:22:55 -0700461
Eric Laurenta609e8e2014-06-18 02:15:17 +0000462 while (!adev->mixer && retry_num < RETRY_NUMBER) {
463 usleep(RETRY_US);
464 adev->mixer = mixer_open(MIXER_CARD);
465 retry_num++;
sangwoo1b9f4b32013-06-21 18:22:55 -0700466 }
467
Eric Laurenta609e8e2014-06-18 02:15:17 +0000468 if (!adev->mixer) {
469 ALOGE("Unable to open the mixer, aborting.");
470 return NULL;
471 }
472
473 snd_card_name = mixer_get_name(adev->mixer);
474 ALOGD("%s: snd_card_name: %s", __func__, snd_card_name);
475
476 adev->audio_route = audio_route_init(MIXER_CARD, MIXER_XML_PATH);
477 if (!adev->audio_route) {
478 ALOGE("%s: Failed to init audio route controls, aborting.", __func__);
sangwoo1b9f4b32013-06-21 18:22:55 -0700479 return NULL;
480 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700481
482 my_data = calloc(1, sizeof(struct platform_data));
483
484 my_data->adev = adev;
485 my_data->dualmic_config = DUALMIC_CONFIG_NONE;
486 my_data->fluence_in_spkr_mode = false;
487 my_data->fluence_in_voice_call = false;
488 my_data->fluence_in_voice_rec = false;
489
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500490 /*
491 * The default assumption is that earpiece (handset), speaker and headphones
492 * devices are connected to internal HW codec and communicated through
493 * slimbus backend. If any platform communicates with speaker or earpiece
494 * or headphones through non-slimbus backend such as MI2S or AUXPCM etc.,
495 * the ext_xxxx flags must be set accordingly.
496 */
497 if (strstr(snd_card_name, "tfa9890_stereo")) {
498 my_data->ext_speaker = true;
499 my_data->ext_earpiece = true;
500 } else if (strstr(snd_card_name, "tfa9890")) {
501 my_data->ext_speaker = true;
502 }
503
Eric Laurentb23d5282013-05-14 15:27:20 -0700504 property_get("persist.audio.dualmic.config",value,"");
505 if (!strcmp("broadside", value)) {
506 my_data->dualmic_config = DUALMIC_CONFIG_BROADSIDE;
507 adev->acdb_settings |= DMIC_FLAG;
508 } else if (!strcmp("endfire", value)) {
509 my_data->dualmic_config = DUALMIC_CONFIG_ENDFIRE;
510 adev->acdb_settings |= DMIC_FLAG;
511 }
512
513 if (my_data->dualmic_config != DUALMIC_CONFIG_NONE) {
514 property_get("persist.audio.fluence.voicecall",value,"");
515 if (!strcmp("true", value)) {
516 my_data->fluence_in_voice_call = true;
517 }
518
519 property_get("persist.audio.fluence.voicerec",value,"");
520 if (!strcmp("true", value)) {
521 my_data->fluence_in_voice_rec = true;
522 }
523
524 property_get("persist.audio.fluence.speaker",value,"");
525 if (!strcmp("true", value)) {
526 my_data->fluence_in_spkr_mode = true;
527 }
528 }
529
530 my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
531 if (my_data->acdb_handle == NULL) {
532 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_ACDB_LOADER);
533 } else {
534 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_ACDB_LOADER);
535 my_data->acdb_deallocate = (acdb_deallocate_t)dlsym(my_data->acdb_handle,
536 "acdb_loader_deallocate_ACDB");
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700537 if (!my_data->acdb_deallocate)
538 ALOGE("%s: Could not find the symbol acdb_loader_deallocate_ACDB from %s",
539 __func__, LIB_ACDB_LOADER);
540
Eric Laurentb23d5282013-05-14 15:27:20 -0700541 my_data->acdb_send_audio_cal = (acdb_send_audio_cal_t)dlsym(my_data->acdb_handle,
542 "acdb_loader_send_audio_cal");
543 if (!my_data->acdb_send_audio_cal)
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700544 ALOGE("%s: Could not find the symbol acdb_send_audio_cal from %s",
Eric Laurentb23d5282013-05-14 15:27:20 -0700545 __func__, LIB_ACDB_LOADER);
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700546
Eric Laurentb23d5282013-05-14 15:27:20 -0700547 my_data->acdb_send_voice_cal = (acdb_send_voice_cal_t)dlsym(my_data->acdb_handle,
548 "acdb_loader_send_voice_cal");
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700549 if (!my_data->acdb_send_voice_cal)
550 ALOGE("%s: Could not find the symbol acdb_loader_send_voice_cal from %s",
551 __func__, LIB_ACDB_LOADER);
552
553 my_data->acdb_reload_vocvoltable = (acdb_reload_vocvoltable_t)dlsym(my_data->acdb_handle,
554 "acdb_loader_reload_vocvoltable");
555 if (!my_data->acdb_reload_vocvoltable)
556 ALOGE("%s: Could not find the symbol acdb_loader_reload_vocvoltable from %s",
557 __func__, LIB_ACDB_LOADER);
558#ifdef PLATFORM_MSM8084
559 my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
560 "acdb_loader_init_v2");
561 if (my_data->acdb_init == NULL)
562 ALOGE("%s: dlsym error %s for acdb_loader_init_v2", __func__, dlerror());
563 else
564 my_data->acdb_init(snd_card_name);
565#else
Eric Laurentb23d5282013-05-14 15:27:20 -0700566 my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
567 "acdb_loader_init_ACDB");
568 if (my_data->acdb_init == NULL)
569 ALOGE("%s: dlsym error %s for acdb_loader_init_ACDB", __func__, dlerror());
570 else
571 my_data->acdb_init();
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700572#endif
Eric Laurentb23d5282013-05-14 15:27:20 -0700573 }
574
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700575 /* load csd client */
576 platform_csd_init(my_data);
577
Eric Laurentb23d5282013-05-14 15:27:20 -0700578 return my_data;
579}
580
581void platform_deinit(void *platform)
582{
583 free(platform);
584}
585
586const char *platform_get_snd_device_name(snd_device_t snd_device)
587{
588 if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX)
589 return device_table[snd_device];
590 else
591 return "";
592}
593
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500594void platform_add_backend_name(void *platform, char *mixer_path,
595 snd_device_t snd_device)
Eric Laurentb23d5282013-05-14 15:27:20 -0700596{
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500597 struct platform_data *my_data = (struct platform_data *)platform;
598
Eric Laurentb23d5282013-05-14 15:27:20 -0700599 if (snd_device == SND_DEVICE_IN_BT_SCO_MIC)
600 strcat(mixer_path, " bt-sco");
601 else if(snd_device == SND_DEVICE_OUT_BT_SCO)
602 strcat(mixer_path, " bt-sco");
603 else if (snd_device == SND_DEVICE_OUT_HDMI)
604 strcat(mixer_path, " hdmi");
605 else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HDMI)
606 strcat(mixer_path, " speaker-and-hdmi");
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -0700607 else if (snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
608 snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB)
609 strcat(mixer_path, " bt-sco-wb");
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500610 else if (my_data->ext_speaker) {
611 if (snd_device == SND_DEVICE_OUT_SPEAKER ||
612 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER ||
613 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE)
614 strcat(mixer_path, " speaker");
615 else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES)
616 strcat(mixer_path, " speaker-and-headphones");
617 } else if (my_data->ext_earpiece &&
618 (snd_device == SND_DEVICE_OUT_VOICE_HANDSET ||
619 snd_device == SND_DEVICE_OUT_VOICE_HANDSET_TMUS ||
620 snd_device == SND_DEVICE_OUT_HANDSET ||
621 snd_device == SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET)) {
622 strcat(mixer_path, " handset");
623 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700624}
625
626int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type)
627{
628 int device_id;
629 if (device_type == PCM_PLAYBACK)
630 device_id = pcm_device_table[usecase][0];
631 else
632 device_id = pcm_device_table[usecase][1];
633 return device_id;
634}
635
636int platform_send_audio_calibration(void *platform, snd_device_t snd_device)
637{
638 struct platform_data *my_data = (struct platform_data *)platform;
639 int acdb_dev_id, acdb_dev_type;
640
641 acdb_dev_id = acdb_device_table[snd_device];
642 if (acdb_dev_id < 0) {
643 ALOGE("%s: Could not find acdb id for device(%d)",
644 __func__, snd_device);
645 return -EINVAL;
646 }
647 if (my_data->acdb_send_audio_cal) {
Eric Laurent994a6932013-07-17 11:51:42 -0700648 ("%s: sending audio calibration for snd_device(%d) acdb_id(%d)",
Eric Laurentb23d5282013-05-14 15:27:20 -0700649 __func__, snd_device, acdb_dev_id);
650 if (snd_device >= SND_DEVICE_OUT_BEGIN &&
651 snd_device < SND_DEVICE_OUT_END)
652 acdb_dev_type = ACDB_DEV_TYPE_OUT;
653 else
654 acdb_dev_type = ACDB_DEV_TYPE_IN;
655 my_data->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type);
656 }
657 return 0;
658}
659
660int platform_switch_voice_call_device_pre(void *platform)
661{
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700662 struct platform_data *my_data = (struct platform_data *)platform;
663 int ret = 0;
664
665 if (my_data->csd != NULL &&
666 my_data->adev->mode == AUDIO_MODE_IN_CALL) {
667 /* This must be called before disabling mixer controls on APQ side */
668 ret = my_data->csd->disable_device();
669 if (ret < 0) {
670 ALOGE("%s: csd_client_disable_device, failed, error %d",
671 __func__, ret);
672 }
673 }
674 return ret;
675}
676
677int platform_switch_voice_call_enable_device_config(void *platform,
678 snd_device_t out_snd_device,
679 snd_device_t in_snd_device)
680{
681 struct platform_data *my_data = (struct platform_data *)platform;
682 int acdb_rx_id, acdb_tx_id;
683 int ret = 0;
684
685 if (my_data->csd == NULL)
686 return ret;
687
688 acdb_rx_id = acdb_device_table[out_snd_device];
689
690 acdb_tx_id = acdb_device_table[in_snd_device];
691
692 if (acdb_rx_id > 0 && acdb_tx_id > 0) {
693 ret = my_data->csd->enable_device_config(acdb_rx_id, acdb_tx_id);
694 if (ret < 0) {
695 ALOGE("%s: csd_enable_device_config, failed, error %d",
696 __func__, ret);
697 }
698 } else {
699 ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__,
700 acdb_rx_id, acdb_tx_id);
701 }
702
703 return ret;
Eric Laurentb23d5282013-05-14 15:27:20 -0700704}
705
706int platform_switch_voice_call_device_post(void *platform,
707 snd_device_t out_snd_device,
708 snd_device_t in_snd_device)
709{
710 struct platform_data *my_data = (struct platform_data *)platform;
711 int acdb_rx_id, acdb_tx_id;
712
713 if (my_data->acdb_send_voice_cal == NULL) {
714 ALOGE("%s: dlsym error for acdb_send_voice_call", __func__);
715 } else {
716 acdb_rx_id = acdb_device_table[out_snd_device];
717 acdb_tx_id = acdb_device_table[in_snd_device];
718
719 if (acdb_rx_id > 0 && acdb_tx_id > 0)
720 my_data->acdb_send_voice_cal(acdb_rx_id, acdb_tx_id);
721 else
722 ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__,
723 acdb_rx_id, acdb_tx_id);
724 }
725
726 return 0;
727}
728
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700729int platform_switch_voice_call_usecase_route_post(void *platform,
730 snd_device_t out_snd_device,
731 snd_device_t in_snd_device)
732{
733 struct platform_data *my_data = (struct platform_data *)platform;
734 int acdb_rx_id, acdb_tx_id;
735 int ret = 0;
736
737 if (my_data->csd == NULL)
738 return ret;
739
740 acdb_rx_id = acdb_device_table[out_snd_device];
741
742 acdb_tx_id = acdb_device_table[in_snd_device];
743
744 if (acdb_rx_id > 0 && acdb_tx_id > 0) {
745 ret = my_data->csd->enable_device(acdb_rx_id, acdb_tx_id,
746 my_data->adev->acdb_settings);
747 if (ret < 0) {
748 ALOGE("%s: csd_enable_device, failed, error %d", __func__, ret);
749 }
750 } else {
751 ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__,
752 acdb_rx_id, acdb_tx_id);
753 }
754
755 return ret;
756}
757
Eric Laurenta609e8e2014-06-18 02:15:17 +0000758int platform_start_voice_call(void *platform)
Eric Laurentb23d5282013-05-14 15:27:20 -0700759{
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700760 struct platform_data *my_data = (struct platform_data *)platform;
761 int ret = 0;
762
763 if (my_data->csd != NULL) {
Eric Laurenta609e8e2014-06-18 02:15:17 +0000764 ret = my_data->csd->start_voice(VOICE_VSID);
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700765 if (ret < 0) {
766 ALOGE("%s: csd_start_voice error %d\n", __func__, ret);
767 }
768 }
769 return ret;
Eric Laurentb23d5282013-05-14 15:27:20 -0700770}
771
Eric Laurenta609e8e2014-06-18 02:15:17 +0000772int platform_stop_voice_call(void *platform)
Eric Laurentb23d5282013-05-14 15:27:20 -0700773{
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700774 struct platform_data *my_data = (struct platform_data *)platform;
775 int ret = 0;
776
777 if (my_data->csd != NULL) {
Eric Laurenta609e8e2014-06-18 02:15:17 +0000778 ret = my_data->csd->stop_voice(VOICE_VSID);
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700779 if (ret < 0) {
780 ALOGE("%s: csd_stop_voice error %d\n", __func__, ret);
781 }
782 }
783 return ret;
Eric Laurentb23d5282013-05-14 15:27:20 -0700784}
785
786int platform_set_voice_volume(void *platform, int volume)
787{
788 struct platform_data *my_data = (struct platform_data *)platform;
789 struct audio_device *adev = my_data->adev;
790 struct mixer_ctl *ctl;
sangwoo53b2cf02013-07-25 19:18:44 -0700791 const char *mixer_ctl_name = "Voice Rx Gain";
Eric Laurenta609e8e2014-06-18 02:15:17 +0000792 int values[VOLUME_CTL_PARAM_NUM];
793 int ret = 0;
Eric Laurentb23d5282013-05-14 15:27:20 -0700794
795 // Voice volume levels are mapped to adsp volume levels as follows.
796 // 100 -> 5, 80 -> 4, 60 -> 3, 40 -> 2, 20 -> 1 0 -> 0
797 // But this values don't changed in kernel. So, below change is need.
Eric Laurenta609e8e2014-06-18 02:15:17 +0000798 volume = (int)percent_to_index(volume, MIN_VOL_INDEX, MAX_VOL_INDEX);
Eric Laurentb23d5282013-05-14 15:27:20 -0700799
800 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
801 if (!ctl) {
802 ALOGE("%s: Could not get ctl for mixer cmd - %s",
803 __func__, mixer_ctl_name);
804 return -EINVAL;
805 }
Eric Laurenta609e8e2014-06-18 02:15:17 +0000806 ret = set_volume_values(VOLUME_SET, volume, values);
807 if (ret < 0) {
808 ALOGV("%s: failed setting volume by incorrect type", __func__);
809 return -EINVAL;
810 }
811 ret = mixer_ctl_set_array(ctl, values, sizeof(values)/sizeof(int));
812 if (ret < 0) {
813 ALOGV("%s: failed set mixer ctl by %d", __func__, ret);
814 return -EINVAL;
815 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700816 if (my_data->csd != NULL) {
817 ret = my_data->csd->volume(ALL_SESSION_VSID, volume,
818 DEFAULT_VOLUME_RAMP_DURATION_MS);
819 if (ret < 0) {
820 ALOGE("%s: csd_volume error %d", __func__, ret);
821 }
822 }
823 return ret;
Eric Laurentb23d5282013-05-14 15:27:20 -0700824}
825
826int platform_set_mic_mute(void *platform, bool state)
827{
828 struct platform_data *my_data = (struct platform_data *)platform;
829 struct audio_device *adev = my_data->adev;
830 struct mixer_ctl *ctl;
831 const char *mixer_ctl_name = "Voice Tx Mute";
Eric Laurenta609e8e2014-06-18 02:15:17 +0000832 int values[VOLUME_CTL_PARAM_NUM];
sangwoo53b2cf02013-07-25 19:18:44 -0700833 int ret = 0;
Eric Laurentb23d5282013-05-14 15:27:20 -0700834
Eric Laurenta609e8e2014-06-18 02:15:17 +0000835 if (adev->mode == AUDIO_MODE_IN_CALL) {
836 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
837 if (!ctl) {
838 ALOGE("%s: Could not get ctl for mixer cmd - %s",
839 __func__, mixer_ctl_name);
840 return -EINVAL;
841 }
842 ALOGV("Setting mic mute: %d", state);
843 ret = set_volume_values(MUTE_SET, state, values);
sangwoo53b2cf02013-07-25 19:18:44 -0700844 if (ret < 0) {
Eric Laurenta609e8e2014-06-18 02:15:17 +0000845 ALOGV("%s: failed setting mute by incorrect type", __func__);
846 return -EINVAL;
847 }
848 ret = mixer_ctl_set_array(ctl, values, sizeof(values)/sizeof(int));
849 if (ret < 0) {
850 ALOGV("%s: failed set mixer ctl by %d", __func__, ret);
851 return -EINVAL;
sangwoo53b2cf02013-07-25 19:18:44 -0700852 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700853 }
854
Eric Laurenta609e8e2014-06-18 02:15:17 +0000855 return 0;
Eric Laurentb23d5282013-05-14 15:27:20 -0700856}
857
858snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices)
859{
860 struct platform_data *my_data = (struct platform_data *)platform;
861 struct audio_device *adev = my_data->adev;
862 audio_mode_t mode = adev->mode;
863 snd_device_t snd_device = SND_DEVICE_NONE;
864
865 ALOGV("%s: enter: output devices(%#x)", __func__, devices);
866 if (devices == AUDIO_DEVICE_NONE ||
867 devices & AUDIO_DEVICE_BIT_IN) {
868 ALOGV("%s: Invalid output devices (%#x)", __func__, devices);
869 goto exit;
870 }
871
872 if (mode == AUDIO_MODE_IN_CALL) {
873 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
874 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Eric Laurenta609e8e2014-06-18 02:15:17 +0000875 if (adev->tty_mode == TTY_MODE_FULL)
Eric Laurentb23d5282013-05-14 15:27:20 -0700876 snd_device = SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES;
Eric Laurenta609e8e2014-06-18 02:15:17 +0000877 else if (adev->tty_mode == TTY_MODE_VCO)
Eric Laurentb23d5282013-05-14 15:27:20 -0700878 snd_device = SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES;
Eric Laurenta609e8e2014-06-18 02:15:17 +0000879 else if (adev->tty_mode == TTY_MODE_HCO)
Eric Laurentb23d5282013-05-14 15:27:20 -0700880 snd_device = SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET;
881 else
882 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES;
883 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -0700884 if (adev->bt_wb_speech_enabled) {
885 snd_device = SND_DEVICE_OUT_BT_SCO_WB;
886 } else {
887 snd_device = SND_DEVICE_OUT_BT_SCO;
888 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700889 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
890 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
891 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
892 if (is_operator_tmus())
893 snd_device = SND_DEVICE_OUT_VOICE_HANDSET_TMUS;
894 else
895 snd_device = SND_DEVICE_OUT_HANDSET;
896 }
897 if (snd_device != SND_DEVICE_NONE) {
898 goto exit;
899 }
900 }
901
902 if (popcount(devices) == 2) {
903 if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
904 AUDIO_DEVICE_OUT_SPEAKER)) {
905 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
906 } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
907 AUDIO_DEVICE_OUT_SPEAKER)) {
908 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
909 } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL |
910 AUDIO_DEVICE_OUT_SPEAKER)) {
911 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
912 } else {
913 ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
914 goto exit;
915 }
916 if (snd_device != SND_DEVICE_NONE) {
917 goto exit;
918 }
919 }
920
921 if (popcount(devices) != 1) {
922 ALOGE("%s: Invalid output devices(%#x)", __func__, devices);
923 goto exit;
924 }
925
926 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
927 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
928 snd_device = SND_DEVICE_OUT_HEADPHONES;
929 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
930 if (adev->speaker_lr_swap)
931 snd_device = SND_DEVICE_OUT_SPEAKER_REVERSE;
932 else
933 snd_device = SND_DEVICE_OUT_SPEAKER;
934 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -0700935 if (adev->bt_wb_speech_enabled) {
936 snd_device = SND_DEVICE_OUT_BT_SCO_WB;
937 } else {
938 snd_device = SND_DEVICE_OUT_BT_SCO;
939 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700940 } else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
941 snd_device = SND_DEVICE_OUT_HDMI ;
942 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
943 snd_device = SND_DEVICE_OUT_HANDSET;
944 } else {
945 ALOGE("%s: Unknown device(s) %#x", __func__, devices);
946 }
947exit:
948 ALOGV("%s: exit: snd_device(%s)", __func__, device_table[snd_device]);
949 return snd_device;
950}
951
952snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device)
953{
954 struct platform_data *my_data = (struct platform_data *)platform;
955 struct audio_device *adev = my_data->adev;
956 audio_source_t source = (adev->active_input == NULL) ?
957 AUDIO_SOURCE_DEFAULT : adev->active_input->source;
958
959 audio_mode_t mode = adev->mode;
960 audio_devices_t in_device = ((adev->active_input == NULL) ?
961 AUDIO_DEVICE_NONE : adev->active_input->device)
962 & ~AUDIO_DEVICE_BIT_IN;
963 audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
964 AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
965 snd_device_t snd_device = SND_DEVICE_NONE;
966
967 ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
968 __func__, out_device, in_device);
969 if (mode == AUDIO_MODE_IN_CALL) {
970 if (out_device == AUDIO_DEVICE_NONE) {
971 ALOGE("%s: No output device set for voice call", __func__);
972 goto exit;
973 }
Eric Laurenta609e8e2014-06-18 02:15:17 +0000974 if (adev->tty_mode != TTY_MODE_OFF) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700975 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
976 out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Eric Laurenta609e8e2014-06-18 02:15:17 +0000977 switch (adev->tty_mode) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700978 case TTY_MODE_FULL:
979 snd_device = SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC;
980 break;
981 case TTY_MODE_VCO:
982 snd_device = SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC;
983 break;
984 case TTY_MODE_HCO:
985 snd_device = SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC;
986 break;
987 default:
Eric Laurenta609e8e2014-06-18 02:15:17 +0000988 ALOGE("%s: Invalid TTY mode (%#x)", __func__, adev->tty_mode);
Eric Laurentb23d5282013-05-14 15:27:20 -0700989 }
990 goto exit;
991 }
992 }
993 if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
994 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
995 if (my_data->fluence_in_voice_call == false) {
996 snd_device = SND_DEVICE_IN_HANDSET_MIC;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800997 set_echo_reference(adev->mixer, "SLIM_RX");
Eric Laurentb23d5282013-05-14 15:27:20 -0700998 } else {
999 if (my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
1000 if (is_operator_tmus())
1001 snd_device = SND_DEVICE_IN_VOICE_DMIC_EF_TMUS;
1002 else
1003 snd_device = SND_DEVICE_IN_VOICE_DMIC_EF;
1004 } else if(my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE)
1005 snd_device = SND_DEVICE_IN_VOICE_DMIC_BS;
1006 else
1007 snd_device = SND_DEVICE_IN_HANDSET_MIC;
1008 }
1009 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
1010 snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
1011 } else if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07001012 if (adev->bt_wb_speech_enabled) {
1013 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
1014 } else {
1015 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
1016 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001017 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
1018 if (my_data->fluence_in_voice_call && my_data->fluence_in_spkr_mode &&
1019 my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
1020 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF;
1021 } else if (my_data->fluence_in_voice_call && my_data->fluence_in_spkr_mode &&
1022 my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE) {
1023 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS;
1024 } else {
1025 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
1026 }
1027 }
1028 } else if (source == AUDIO_SOURCE_CAMCORDER) {
1029 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
1030 in_device & AUDIO_DEVICE_IN_BACK_MIC) {
1031 snd_device = SND_DEVICE_IN_CAMCORDER_MIC;
1032 }
1033 } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) {
1034 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
1035 if (my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
1036 if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
1037 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_EF;
1038 else if (my_data->fluence_in_voice_rec)
1039 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE;
1040 } else if (my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE) {
1041 if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
1042 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_BS;
1043 else if (my_data->fluence_in_voice_rec)
1044 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE;
1045 }
1046
1047 if (snd_device == SND_DEVICE_NONE) {
1048 snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
1049 }
1050 }
1051 } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1052 if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
1053 in_device = AUDIO_DEVICE_IN_BACK_MIC;
1054 if (adev->active_input) {
1055 if (adev->active_input->enable_aec) {
1056 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
1057 snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
1058 } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
1059 snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
1060 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
1061 snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
1062 }
1063 set_echo_reference(adev->mixer, "SLIM_RX");
1064 } else
1065 set_echo_reference(adev->mixer, "NONE");
1066 }
1067 } else if (source == AUDIO_SOURCE_DEFAULT) {
1068 goto exit;
1069 }
1070
1071
1072 if (snd_device != SND_DEVICE_NONE) {
1073 goto exit;
1074 }
1075
1076 if (in_device != AUDIO_DEVICE_NONE &&
1077 !(in_device & AUDIO_DEVICE_IN_VOICE_CALL) &&
1078 !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) {
1079 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
1080 snd_device = SND_DEVICE_IN_HANDSET_MIC;
1081 } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
1082 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
1083 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
1084 snd_device = SND_DEVICE_IN_HEADSET_MIC;
1085 } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07001086 if (adev->bt_wb_speech_enabled) {
1087 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
1088 } else {
1089 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
1090 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001091 } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) {
1092 snd_device = SND_DEVICE_IN_HDMI_MIC;
1093 } else {
1094 ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
1095 ALOGW("%s: Using default handset-mic", __func__);
1096 snd_device = SND_DEVICE_IN_HANDSET_MIC;
1097 }
1098 } else {
1099 if (out_device & AUDIO_DEVICE_OUT_EARPIECE) {
1100 snd_device = SND_DEVICE_IN_HANDSET_MIC;
1101 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
1102 snd_device = SND_DEVICE_IN_HEADSET_MIC;
1103 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
1104 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
1105 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
1106 snd_device = SND_DEVICE_IN_HANDSET_MIC;
1107 } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07001108 if (adev->bt_wb_speech_enabled) {
1109 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
1110 } else {
1111 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
1112 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001113 } else if (out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1114 snd_device = SND_DEVICE_IN_HDMI_MIC;
1115 } else {
1116 ALOGE("%s: Unknown output device(s) %#x", __func__, out_device);
1117 ALOGW("%s: Using default handset-mic", __func__);
1118 snd_device = SND_DEVICE_IN_HANDSET_MIC;
1119 }
1120 }
1121exit:
1122 ALOGV("%s: exit: in_snd_device(%s)", __func__, device_table[snd_device]);
1123 return snd_device;
1124}
1125
1126int platform_set_hdmi_channels(void *platform, int channel_count)
1127{
1128 struct platform_data *my_data = (struct platform_data *)platform;
1129 struct audio_device *adev = my_data->adev;
1130 struct mixer_ctl *ctl;
1131 const char *channel_cnt_str = NULL;
1132 const char *mixer_ctl_name = "HDMI_RX Channels";
1133 switch (channel_count) {
1134 case 8:
1135 channel_cnt_str = "Eight"; break;
1136 case 7:
1137 channel_cnt_str = "Seven"; break;
1138 case 6:
1139 channel_cnt_str = "Six"; break;
1140 case 5:
1141 channel_cnt_str = "Five"; break;
1142 case 4:
1143 channel_cnt_str = "Four"; break;
1144 case 3:
1145 channel_cnt_str = "Three"; break;
1146 default:
1147 channel_cnt_str = "Two"; break;
1148 }
1149 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1150 if (!ctl) {
1151 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1152 __func__, mixer_ctl_name);
1153 return -EINVAL;
1154 }
1155 ALOGV("HDMI channel count: %s", channel_cnt_str);
1156 mixer_ctl_set_enum_by_string(ctl, channel_cnt_str);
1157 return 0;
1158}
1159
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001160int platform_edid_get_max_channels(void *platform)
Eric Laurentb23d5282013-05-14 15:27:20 -07001161{
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001162 struct platform_data *my_data = (struct platform_data *)platform;
1163 struct audio_device *adev = my_data->adev;
Eric Laurentb23d5282013-05-14 15:27:20 -07001164 char block[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE];
1165 char *sad = block;
1166 int num_audio_blocks;
1167 int channel_count;
1168 int max_channels = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001169 int i, ret, count;
Eric Laurentb23d5282013-05-14 15:27:20 -07001170
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001171 struct mixer_ctl *ctl;
1172
1173 ctl = mixer_get_ctl_by_name(adev->mixer, AUDIO_DATA_BLOCK_MIXER_CTL);
1174 if (!ctl) {
1175 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1176 __func__, AUDIO_DATA_BLOCK_MIXER_CTL);
Eric Laurentb23d5282013-05-14 15:27:20 -07001177 return 0;
1178 }
1179
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001180 mixer_ctl_update(ctl);
1181
1182 count = mixer_ctl_get_num_values(ctl);
Eric Laurentb23d5282013-05-14 15:27:20 -07001183
1184 /* Read SAD blocks, clamping the maximum size for safety */
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001185 if (count > (int)sizeof(block))
1186 count = (int)sizeof(block);
Eric Laurentb23d5282013-05-14 15:27:20 -07001187
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001188 ret = mixer_ctl_get_array(ctl, block, count);
1189 if (ret != 0) {
1190 ALOGE("%s: mixer_ctl_get_array() failed to get EDID info", __func__);
1191 return 0;
1192 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001193
1194 /* Calculate the number of SAD blocks */
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001195 num_audio_blocks = count / SAD_BLOCK_SIZE;
Eric Laurentb23d5282013-05-14 15:27:20 -07001196
1197 for (i = 0; i < num_audio_blocks; i++) {
1198 /* Only consider LPCM blocks */
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001199 if ((sad[0] >> 3) != EDID_FORMAT_LPCM) {
1200 sad += 3;
Eric Laurentb23d5282013-05-14 15:27:20 -07001201 continue;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001202 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001203
1204 channel_count = (sad[0] & 0x7) + 1;
1205 if (channel_count > max_channels)
1206 max_channels = channel_count;
1207
1208 /* Advance to next block */
1209 sad += 3;
1210 }
1211
1212 return max_channels;
1213}
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07001214
1215/* Delay in Us */
1216int64_t platform_render_latency(audio_usecase_t usecase)
1217{
1218 switch (usecase) {
1219 case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER:
1220 return DEEP_BUFFER_PLATFORM_DELAY;
1221 case USECASE_AUDIO_PLAYBACK_LOW_LATENCY:
1222 return LOW_LATENCY_PLATFORM_DELAY;
1223 default:
1224 return 0;
1225 }
1226}