blob: e80aa270fd6d9f6d9432a0806af18e4387798236 [file] [log] [blame]
Eric Laurentb23d5282013-05-14 15:27:20 -07001/*
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
3 * Not a contribution.
4 *
Eric Laurentb23d5282013-05-14 15:27:20 -07005 * Copyright (C) 2013 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20#define LOG_TAG "msm8960_platform"
21/*#define LOG_NDEBUG 0*/
22#define LOG_NDDEBUG 0
23
24#include <stdlib.h>
25#include <dlfcn.h>
26#include <cutils/log.h>
27#include <cutils/properties.h>
28#include <audio_hw.h>
29#include <platform_api.h>
30#include "platform.h"
31
32#define LIB_ACDB_LOADER "libacdbloader.so"
33#define LIB_CSD_CLIENT "libcsd-client.so"
34
Eric Laurentb23d5282013-05-14 15:27:20 -070035/*
36 * This is the sysfs path for the HDMI audio data block
37 */
38#define AUDIO_DATA_BLOCK_PATH "/sys/class/graphics/fb1/audio_data_block"
sangwoo1b9f4b32013-06-21 18:22:55 -070039#define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
Eric Laurentb23d5282013-05-14 15:27:20 -070040
41/*
42 * 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
54struct audio_block_header
55{
56 int reserved;
57 int length;
58};
59
60
61typedef void (*acdb_deallocate_t)();
62typedef int (*acdb_init_t)();
63typedef void (*acdb_send_audio_cal_t)(int, int);
64typedef void (*acdb_send_voice_cal_t)(int, int);
65
66typedef int (*csd_client_init_t)();
67typedef int (*csd_client_deinit_t)();
68typedef int (*csd_disable_device_t)();
69typedef int (*csd_enable_device_t)(int, int, uint32_t);
70typedef int (*csd_volume_t)(int);
71typedef int (*csd_mic_mute_t)(int);
72typedef int (*csd_start_voice_t)();
73typedef int (*csd_stop_voice_t)();
74
75
Eric Laurentb23d5282013-05-14 15:27:20 -070076struct platform_data {
77 struct audio_device *adev;
78 bool fluence_in_spkr_mode;
79 bool fluence_in_voice_call;
80 bool fluence_in_voice_rec;
Mingming Yin8e5a4f62013-10-07 15:23:41 -070081 int fluence_type;
Eric Laurentb23d5282013-05-14 15:27:20 -070082 int dualmic_config;
83
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -070084 void *hw_info;
85
86 /* Audio calibration related functions */
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;
92
93 /* CSD Client related functions for voice call */
94 void *csd_client;
95 csd_client_init_t csd_client_init;
96 csd_client_deinit_t csd_client_deinit;
97 csd_disable_device_t csd_disable_device;
98 csd_enable_device_t csd_enable_device;
99 csd_volume_t csd_volume;
100 csd_mic_mute_t csd_mic_mute;
101 csd_start_voice_t csd_start_voice;
102 csd_stop_voice_t csd_stop_voice;
103};
104
105static const int pcm_device_table[AUDIO_USECASE_MAX][2] = {
106 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
107 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {14, 14},
108 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
109 [USECASE_AUDIO_RECORD] = {0, 0},
110 [USECASE_AUDIO_RECORD_LOW_LATENCY] = {14, 14},
111 [USECASE_VOICE_CALL] = {12, 12},
112};
113
114/* Array to store sound devices */
115static const char * const device_table[SND_DEVICE_MAX] = {
116 [SND_DEVICE_NONE] = "none",
117 /* Playback sound devices */
118 [SND_DEVICE_OUT_HANDSET] = "handset",
119 [SND_DEVICE_OUT_SPEAKER] = "speaker",
120 [SND_DEVICE_OUT_SPEAKER_REVERSE] = "speaker-reverse",
121 [SND_DEVICE_OUT_HEADPHONES] = "headphones",
122 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones",
123 [SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker",
124 [SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones",
125 [SND_DEVICE_OUT_HDMI] = "hdmi",
126 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
127 [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
128 [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = "voice-handset-tmus",
129 [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = "voice-tty-full-headphones",
130 [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = "voice-tty-vco-headphones",
131 [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = "voice-tty-hco-handset",
132
133 /* Capture sound devices */
134 [SND_DEVICE_IN_HANDSET_MIC] = "handset-mic",
135 [SND_DEVICE_IN_SPEAKER_MIC] = "speaker-mic",
136 [SND_DEVICE_IN_HEADSET_MIC] = "headset-mic",
137 [SND_DEVICE_IN_HANDSET_MIC_AEC] = "handset-mic",
138 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = "voice-speaker-mic",
139 [SND_DEVICE_IN_HEADSET_MIC_AEC] = "headset-mic",
140 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "voice-speaker-mic",
141 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "voice-headset-mic",
142 [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic",
143 [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic",
144 [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic",
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700145 [SND_DEVICE_IN_VOICE_DMIC] = "voice-dmic-ef",
146 [SND_DEVICE_IN_VOICE_DMIC_TMUS] = "voice-dmic-ef-tmus",
147 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC] = "voice-speaker-dmic-ef",
Eric Laurentb23d5282013-05-14 15:27:20 -0700148 [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = "voice-tty-full-headset-mic",
149 [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = "voice-tty-vco-handset-mic",
150 [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = "voice-tty-hco-headset-mic",
151 [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic",
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700152 [SND_DEVICE_IN_VOICE_REC_DMIC] = "voice-rec-dmic-ef",
153 [SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE] = "voice-rec-dmic-ef-fluence",
Eric Laurentb23d5282013-05-14 15:27:20 -0700154};
155
156/* ACDB IDs (audio DSP path configuration IDs) for each sound device */
157static const int acdb_device_table[SND_DEVICE_MAX] = {
158 [SND_DEVICE_NONE] = -1,
159 [SND_DEVICE_OUT_HANDSET] = 7,
160 [SND_DEVICE_OUT_SPEAKER] = 14,
161 [SND_DEVICE_OUT_SPEAKER_REVERSE] = 14,
162 [SND_DEVICE_OUT_HEADPHONES] = 10,
163 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = 10,
164 [SND_DEVICE_OUT_VOICE_SPEAKER] = 14,
165 [SND_DEVICE_OUT_VOICE_HEADPHONES] = 10,
166 [SND_DEVICE_OUT_HDMI] = 18,
167 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 14,
168 [SND_DEVICE_OUT_BT_SCO] = 22,
169 [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = 81,
170 [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = 17,
171 [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = 17,
172 [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = 37,
173
174 [SND_DEVICE_IN_HANDSET_MIC] = 4,
175 [SND_DEVICE_IN_SPEAKER_MIC] = 4,
176 [SND_DEVICE_IN_HEADSET_MIC] = 8,
177 [SND_DEVICE_IN_HANDSET_MIC_AEC] = 40,
178 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = 42,
179 [SND_DEVICE_IN_HEADSET_MIC_AEC] = 47,
180 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = 11,
181 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = 8,
182 [SND_DEVICE_IN_HDMI_MIC] = 4,
183 [SND_DEVICE_IN_BT_SCO_MIC] = 21,
184 [SND_DEVICE_IN_CAMCORDER_MIC] = 61,
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700185 [SND_DEVICE_IN_VOICE_DMIC] = 6,
186 [SND_DEVICE_IN_VOICE_DMIC_TMUS] = 91,
187 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC] = 13,
Eric Laurentb23d5282013-05-14 15:27:20 -0700188 [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = 16,
189 [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = 36,
190 [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = 16,
191 [SND_DEVICE_IN_VOICE_REC_MIC] = 62,
192 /* TODO: Update with proper acdb ids */
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700193 [SND_DEVICE_IN_VOICE_REC_DMIC] = 62,
194 [SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE] = 6,
Eric Laurentb23d5282013-05-14 15:27:20 -0700195};
196
Haynes Mathew George7ff216f2013-09-11 19:51:41 -0700197#define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL)
198#define LOW_LATENCY_PLATFORM_DELAY (13*1000LL)
199
Eric Laurentb23d5282013-05-14 15:27:20 -0700200static pthread_once_t check_op_once_ctl = PTHREAD_ONCE_INIT;
201static bool is_tmus = false;
202
203static void check_operator()
204{
205 char value[PROPERTY_VALUE_MAX];
206 int mccmnc;
207 property_get("gsm.sim.operator.numeric",value,"0");
208 mccmnc = atoi(value);
209 ALOGD("%s: tmus mccmnc %d", __func__, mccmnc);
210 switch(mccmnc) {
211 /* TMUS MCC(310), MNC(490, 260, 026) */
212 case 310490:
213 case 310260:
214 case 310026:
215 is_tmus = true;
216 break;
217 }
218}
219
220bool is_operator_tmus()
221{
222 pthread_once(&check_op_once_ctl, check_operator);
223 return is_tmus;
224}
225
226static int set_echo_reference(struct mixer *mixer, const char* ec_ref)
227{
228 struct mixer_ctl *ctl;
229 const char *mixer_ctl_name = "EC_REF_RX";
230
231 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
232 if (!ctl) {
233 ALOGE("%s: Could not get ctl for mixer cmd - %s",
234 __func__, mixer_ctl_name);
235 return -EINVAL;
236 }
237 ALOGV("Setting EC Reference: %s", ec_ref);
238 mixer_ctl_set_enum_by_string(ctl, ec_ref);
239 return 0;
240}
241
242void *platform_init(struct audio_device *adev)
243{
244 char platform[PROPERTY_VALUE_MAX];
245 char baseband[PROPERTY_VALUE_MAX];
246 char value[PROPERTY_VALUE_MAX];
247 struct platform_data *my_data;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700248 const char *snd_card_name;
Eric Laurentb23d5282013-05-14 15:27:20 -0700249
sangwoo1b9f4b32013-06-21 18:22:55 -0700250 adev->mixer = mixer_open(MIXER_CARD);
251
252 if (!adev->mixer) {
253 ALOGE("Unable to open the mixer, aborting.");
254 return NULL;
255 }
256
257 adev->audio_route = audio_route_init(MIXER_CARD, MIXER_XML_PATH);
258 if (!adev->audio_route) {
259 ALOGE("%s: Failed to init audio route controls, aborting.", __func__);
260 return NULL;
261 }
262
Eric Laurentb23d5282013-05-14 15:27:20 -0700263 my_data = calloc(1, sizeof(struct platform_data));
264
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700265 snd_card_name = mixer_get_name(adev->mixer);
266 my_data->hw_info = hw_info_init(snd_card_name);
267 if (!my_data->hw_info) {
268 ALOGE("%s: Failed to init hardware info", __func__);
269 }
270
Eric Laurentb23d5282013-05-14 15:27:20 -0700271 my_data->adev = adev;
Eric Laurentb23d5282013-05-14 15:27:20 -0700272 my_data->fluence_in_spkr_mode = false;
273 my_data->fluence_in_voice_call = false;
274 my_data->fluence_in_voice_rec = false;
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700275 my_data->fluence_type = FLUENCE_NONE;
Eric Laurentb23d5282013-05-14 15:27:20 -0700276
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700277 property_get("ro.qc.sdk.audio.fluencetype", value, "");
278 if (!strncmp("fluencepro", value, sizeof("fluencepro"))) {
279 my_data->fluence_type = FLUENCE_QUAD_MIC;
280 } else if (!strncmp("fluence", value, sizeof("fluence"))) {
281 my_data->fluence_type = FLUENCE_DUAL_MIC;
282 } else {
283 my_data->fluence_type = FLUENCE_NONE;
Eric Laurentb23d5282013-05-14 15:27:20 -0700284 }
285
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700286 if (my_data->fluence_type != FLUENCE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700287 property_get("persist.audio.fluence.voicecall",value,"");
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700288 if (!strncmp("true", value, sizeof("true"))) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700289 my_data->fluence_in_voice_call = true;
290 }
291
292 property_get("persist.audio.fluence.voicerec",value,"");
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700293 if (!strncmp("true", value, sizeof("true"))) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700294 my_data->fluence_in_voice_rec = true;
295 }
296
297 property_get("persist.audio.fluence.speaker",value,"");
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700298 if (!strncmp("true", value, sizeof("true"))) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700299 my_data->fluence_in_spkr_mode = true;
300 }
301 }
302
303 my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
304 if (my_data->acdb_handle == NULL) {
305 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_ACDB_LOADER);
306 } else {
307 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_ACDB_LOADER);
308 my_data->acdb_deallocate = (acdb_deallocate_t)dlsym(my_data->acdb_handle,
309 "acdb_loader_deallocate_ACDB");
310 my_data->acdb_send_audio_cal = (acdb_send_audio_cal_t)dlsym(my_data->acdb_handle,
311 "acdb_loader_send_audio_cal");
312 if (!my_data->acdb_send_audio_cal)
313 ALOGW("%s: Could not find the symbol acdb_send_audio_cal from %s",
314 __func__, LIB_ACDB_LOADER);
315 my_data->acdb_send_voice_cal = (acdb_send_voice_cal_t)dlsym(my_data->acdb_handle,
316 "acdb_loader_send_voice_cal");
317 my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
318 "acdb_loader_init_ACDB");
319 if (my_data->acdb_init == NULL)
320 ALOGE("%s: dlsym error %s for acdb_loader_init_ACDB", __func__, dlerror());
321 else
322 my_data->acdb_init();
323 }
324
325 /* If platform is Fusion3, load CSD Client specific symbols
326 * Voice call is handled by MDM and apps processor talks to
327 * MDM through CSD Client
328 */
329 property_get("ro.board.platform", platform, "");
330 property_get("ro.baseband", baseband, "");
331 if (!strcmp("msm8960", platform) && !strcmp("mdm", baseband)) {
332 my_data->csd_client = dlopen(LIB_CSD_CLIENT, RTLD_NOW);
333 if (my_data->csd_client == NULL)
334 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_CSD_CLIENT);
335 }
336
337 if (my_data->csd_client) {
338 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_CSD_CLIENT);
339 my_data->csd_client_deinit = (csd_client_deinit_t)dlsym(my_data->csd_client,
340 "csd_client_deinit");
341 my_data->csd_disable_device = (csd_disable_device_t)dlsym(my_data->csd_client,
342 "csd_client_disable_device");
343 my_data->csd_enable_device = (csd_enable_device_t)dlsym(my_data->csd_client,
344 "csd_client_enable_device");
345 my_data->csd_start_voice = (csd_start_voice_t)dlsym(my_data->csd_client,
346 "csd_client_start_voice");
347 my_data->csd_stop_voice = (csd_stop_voice_t)dlsym(my_data->csd_client,
348 "csd_client_stop_voice");
349 my_data->csd_volume = (csd_volume_t)dlsym(my_data->csd_client,
350 "csd_client_volume");
351 my_data->csd_mic_mute = (csd_mic_mute_t)dlsym(my_data->csd_client,
352 "csd_client_mic_mute");
353 my_data->csd_client_init = (csd_client_init_t)dlsym(my_data->csd_client,
354 "csd_client_init");
355
356 if (my_data->csd_client_init == NULL) {
357 ALOGE("%s: dlsym error %s for csd_client_init", __func__, dlerror());
358 } else {
359 my_data->csd_client_init();
360 }
361 }
362
363 return my_data;
364}
365
366void platform_deinit(void *platform)
367{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700368 struct platform_data *my_data = (struct platform_data *)platform;
369
370 hw_info_deinit(my_data->hw_info);
Eric Laurentb23d5282013-05-14 15:27:20 -0700371 free(platform);
372}
373
374const char *platform_get_snd_device_name(snd_device_t snd_device)
375{
376 if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX)
377 return device_table[snd_device];
378 else
379 return "";
380}
381
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700382int platform_get_snd_device_name_extn(void *platform, snd_device_t snd_device,
383 char *device_name)
384{
385 struct platform_data *my_data = (struct platform_data *)platform;
386
387 if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX) {
388 strlcpy(device_name, device_table[snd_device], DEVICE_NAME_MAX_SIZE);
389 hw_info_append_hw_type(my_data->hw_info, snd_device, device_name);
390 } else {
391 strlcpy(device_name, "", DEVICE_NAME_MAX_SIZE);
392 return -EINVAL;
393 }
394
395 return 0;
396}
397
Eric Laurentb23d5282013-05-14 15:27:20 -0700398void platform_add_backend_name(char *mixer_path, snd_device_t snd_device)
399{
400 if (snd_device == SND_DEVICE_IN_BT_SCO_MIC)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700401 strlcat(mixer_path, " bt-sco", MIXER_PATH_MAX_LENGTH);
402 else if (snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB)
403 strlcat(mixer_path, " bt-sco-wb", MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700404 else if(snd_device == SND_DEVICE_OUT_BT_SCO)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700405 strlcat(mixer_path, " bt-sco", MIXER_PATH_MAX_LENGTH);
406 else if(snd_device == SND_DEVICE_OUT_BT_SCO_WB)
407 strlcat(mixer_path, " bt-sco-wb", MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700408 else if (snd_device == SND_DEVICE_OUT_HDMI)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700409 strlcat(mixer_path, " hdmi", MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700410 else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HDMI)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700411 strlcat(mixer_path, " speaker-and-hdmi", MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700412}
413
414int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type)
415{
416 int device_id;
417 if (device_type == PCM_PLAYBACK)
418 device_id = pcm_device_table[usecase][0];
419 else
420 device_id = pcm_device_table[usecase][1];
421 return device_id;
422}
423
424int platform_send_audio_calibration(void *platform, snd_device_t snd_device)
425{
426 struct platform_data *my_data = (struct platform_data *)platform;
427 int acdb_dev_id, acdb_dev_type;
428
429 acdb_dev_id = acdb_device_table[snd_device];
430 if (acdb_dev_id < 0) {
431 ALOGE("%s: Could not find acdb id for device(%d)",
432 __func__, snd_device);
433 return -EINVAL;
434 }
435 if (my_data->acdb_send_audio_cal) {
Eric Laurent994a6932013-07-17 11:51:42 -0700436 ("%s: sending audio calibration for snd_device(%d) acdb_id(%d)",
Eric Laurentb23d5282013-05-14 15:27:20 -0700437 __func__, snd_device, acdb_dev_id);
438 if (snd_device >= SND_DEVICE_OUT_BEGIN &&
439 snd_device < SND_DEVICE_OUT_END)
440 acdb_dev_type = ACDB_DEV_TYPE_OUT;
441 else
442 acdb_dev_type = ACDB_DEV_TYPE_IN;
443 my_data->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type);
444 }
445 return 0;
446}
447
448int platform_switch_voice_call_device_pre(void *platform)
449{
450 struct platform_data *my_data = (struct platform_data *)platform;
451 int ret = 0;
452
453 if (my_data->csd_client != NULL) {
454 /* This must be called before disabling the mixer controls on APQ side */
455 if (my_data->csd_disable_device == NULL) {
456 ALOGE("%s: dlsym error for csd_disable_device", __func__);
457 } else {
458 ret = my_data->csd_disable_device();
459 if (ret < 0) {
460 ALOGE("%s: csd_client_disable_device, failed, error %d",
461 __func__, ret);
462 }
463 }
464 }
465 return ret;
466}
467
468int platform_switch_voice_call_device_post(void *platform,
469 snd_device_t out_snd_device,
470 snd_device_t in_snd_device)
471{
472 struct platform_data *my_data = (struct platform_data *)platform;
473 int acdb_rx_id, acdb_tx_id;
474 int ret = 0;
475
476 if (my_data->csd_client) {
477 if (my_data->csd_enable_device == NULL) {
478 ALOGE("%s: dlsym error for csd_enable_device",
479 __func__);
480 } else {
481 acdb_rx_id = acdb_device_table[out_snd_device];
482 acdb_tx_id = acdb_device_table[in_snd_device];
483
484 if (acdb_rx_id > 0 || acdb_tx_id > 0) {
485 ret = my_data->csd_enable_device(acdb_rx_id, acdb_tx_id,
486 my_data->adev->acdb_settings);
487 if (ret < 0) {
488 ALOGE("%s: csd_enable_device, failed, error %d",
489 __func__, ret);
490 }
491 } else {
492 ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__,
493 acdb_rx_id, acdb_tx_id);
494 }
495 }
496 }
497
498 return ret;
499}
500
501int platform_start_voice_call(void *platform)
502{
503 struct platform_data *my_data = (struct platform_data *)platform;
504 int ret = 0;
505
506 if (my_data->csd_client) {
507 if (my_data->csd_start_voice == NULL) {
508 ALOGE("dlsym error for csd_client_start_voice");
509 ret = -ENOSYS;
510 } else {
511 ret = my_data->csd_start_voice();
512 if (ret < 0) {
513 ALOGE("%s: csd_start_voice error %d\n", __func__, ret);
514 }
515 }
516 }
517
518 return ret;
519}
520
521int platform_stop_voice_call(void *platform)
522{
523 struct platform_data *my_data = (struct platform_data *)platform;
524 int ret = 0;
525
526 if (my_data->csd_client) {
527 if (my_data->csd_stop_voice == NULL) {
528 ALOGE("dlsym error for csd_stop_voice");
529 } else {
530 ret = my_data->csd_stop_voice();
531 if (ret < 0) {
532 ALOGE("%s: csd_stop_voice error %d\n", __func__, ret);
533 }
534 }
535 }
536
537 return ret;
538}
539
540int platform_set_voice_volume(void *platform, int volume)
541{
542 struct platform_data *my_data = (struct platform_data *)platform;
543 int ret = 0;
544
545 if (my_data->csd_client) {
546 if (my_data->csd_volume == NULL) {
547 ALOGE("%s: dlsym error for csd_volume", __func__);
548 } else {
549 ret = my_data->csd_volume(volume);
550 if (ret < 0) {
551 ALOGE("%s: csd_volume error %d", __func__, ret);
552 }
553 }
554 } else {
555 ALOGE("%s: No CSD Client present", __func__);
556 }
557
558 return ret;
559}
560
561int platform_set_mic_mute(void *platform, bool state)
562{
563 struct platform_data *my_data = (struct platform_data *)platform;
564 int ret = 0;
565
566 if (my_data->adev->mode == AUDIO_MODE_IN_CALL) {
567 if (my_data->csd_client) {
568 if (my_data->csd_mic_mute == NULL) {
569 ALOGE("%s: dlsym error for csd_mic_mute", __func__);
570 } else {
571 ret = my_data->csd_mic_mute(state);
572 if (ret < 0) {
573 ALOGE("%s: csd_mic_mute error %d", __func__, ret);
574 }
575 }
576 } else {
577 ALOGE("%s: No CSD Client present", __func__);
578 }
579 }
580
581 return ret;
582}
583
584snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices)
585{
586 struct platform_data *my_data = (struct platform_data *)platform;
587 struct audio_device *adev = my_data->adev;
588 audio_mode_t mode = adev->mode;
589 snd_device_t snd_device = SND_DEVICE_NONE;
590
591 ALOGV("%s: enter: output devices(%#x)", __func__, devices);
592 if (devices == AUDIO_DEVICE_NONE ||
593 devices & AUDIO_DEVICE_BIT_IN) {
594 ALOGV("%s: Invalid output devices (%#x)", __func__, devices);
595 goto exit;
596 }
597
598 if (mode == AUDIO_MODE_IN_CALL) {
599 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
600 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
601 if (adev->tty_mode == TTY_MODE_FULL)
602 snd_device = SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES;
603 else if (adev->tty_mode == TTY_MODE_VCO)
604 snd_device = SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES;
605 else if (adev->tty_mode == TTY_MODE_HCO)
606 snd_device = SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET;
607 else
608 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES;
609 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
610 snd_device = SND_DEVICE_OUT_BT_SCO;
611 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
612 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
613 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
614 if (is_operator_tmus())
615 snd_device = SND_DEVICE_OUT_VOICE_HANDSET_TMUS;
616 else
617 snd_device = SND_DEVICE_OUT_HANDSET;
618 }
619 if (snd_device != SND_DEVICE_NONE) {
620 goto exit;
621 }
622 }
623
624 if (popcount(devices) == 2) {
625 if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
626 AUDIO_DEVICE_OUT_SPEAKER)) {
627 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
628 } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
629 AUDIO_DEVICE_OUT_SPEAKER)) {
630 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
631 } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL |
632 AUDIO_DEVICE_OUT_SPEAKER)) {
633 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
634 } else {
635 ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
636 goto exit;
637 }
638 if (snd_device != SND_DEVICE_NONE) {
639 goto exit;
640 }
641 }
642
643 if (popcount(devices) != 1) {
644 ALOGE("%s: Invalid output devices(%#x)", __func__, devices);
645 goto exit;
646 }
647
648 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
649 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
650 snd_device = SND_DEVICE_OUT_HEADPHONES;
651 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
652 if (adev->speaker_lr_swap)
653 snd_device = SND_DEVICE_OUT_SPEAKER_REVERSE;
654 else
655 snd_device = SND_DEVICE_OUT_SPEAKER;
656 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
657 snd_device = SND_DEVICE_OUT_BT_SCO;
658 } else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
659 snd_device = SND_DEVICE_OUT_HDMI ;
660 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
661 snd_device = SND_DEVICE_OUT_HANDSET;
662 } else {
663 ALOGE("%s: Unknown device(s) %#x", __func__, devices);
664 }
665exit:
666 ALOGV("%s: exit: snd_device(%s)", __func__, device_table[snd_device]);
667 return snd_device;
668}
669
670snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device)
671{
672 struct platform_data *my_data = (struct platform_data *)platform;
673 struct audio_device *adev = my_data->adev;
674 audio_source_t source = (adev->active_input == NULL) ?
675 AUDIO_SOURCE_DEFAULT : adev->active_input->source;
676
677 audio_mode_t mode = adev->mode;
678 audio_devices_t in_device = ((adev->active_input == NULL) ?
679 AUDIO_DEVICE_NONE : adev->active_input->device)
680 & ~AUDIO_DEVICE_BIT_IN;
681 audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
682 AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
683 snd_device_t snd_device = SND_DEVICE_NONE;
684
685 ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
686 __func__, out_device, in_device);
687 if (mode == AUDIO_MODE_IN_CALL) {
688 if (out_device == AUDIO_DEVICE_NONE) {
689 ALOGE("%s: No output device set for voice call", __func__);
690 goto exit;
691 }
692 if (adev->tty_mode != TTY_MODE_OFF) {
693 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
694 out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
695 switch (adev->tty_mode) {
696 case TTY_MODE_FULL:
697 snd_device = SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC;
698 break;
699 case TTY_MODE_VCO:
700 snd_device = SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC;
701 break;
702 case TTY_MODE_HCO:
703 snd_device = SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC;
704 break;
705 default:
706 ALOGE("%s: Invalid TTY mode (%#x)", __func__, adev->tty_mode);
707 }
708 goto exit;
709 }
710 }
711 if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
712 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700713 if (my_data->fluence_type == FLUENCE_NONE ||
714 my_data->fluence_in_voice_call == false) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700715 snd_device = SND_DEVICE_IN_HANDSET_MIC;
716 } else {
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700717 if (is_operator_tmus())
718 snd_device = SND_DEVICE_IN_VOICE_DMIC_TMUS;
Eric Laurentb23d5282013-05-14 15:27:20 -0700719 else
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700720 snd_device = SND_DEVICE_IN_VOICE_DMIC;
721 adev->acdb_settings |= DMIC_FLAG;
Eric Laurentb23d5282013-05-14 15:27:20 -0700722 }
723 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
724 snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
725 } else if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
726 snd_device = SND_DEVICE_IN_BT_SCO_MIC ;
727 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700728 if (my_data->fluence_type != FLUENCE_NONE &&
729 my_data->fluence_in_voice_call &&
730 my_data->fluence_in_spkr_mode) {
731 if(my_data->fluence_type == FLUENCE_DUAL_MIC) {
732 adev->acdb_settings |= DMIC_FLAG;
733 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC;
734 } else {
735 adev->acdb_settings |= QMIC_FLAG;
736 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_QMIC;
737 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700738 } else {
739 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
740 }
741 }
742 } else if (source == AUDIO_SOURCE_CAMCORDER) {
743 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
744 in_device & AUDIO_DEVICE_IN_BACK_MIC) {
745 snd_device = SND_DEVICE_IN_CAMCORDER_MIC;
746 }
747 } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) {
748 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700749 if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
750 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC;
751 else if (my_data->fluence_in_voice_rec)
752 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE;
Eric Laurentb23d5282013-05-14 15:27:20 -0700753
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700754 if (snd_device == SND_DEVICE_NONE)
Eric Laurentb23d5282013-05-14 15:27:20 -0700755 snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700756 else
757 adev->acdb_settings |= DMIC_FLAG;
Eric Laurentb23d5282013-05-14 15:27:20 -0700758 }
759 } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
760 if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
761 in_device = AUDIO_DEVICE_IN_BACK_MIC;
762 if (adev->active_input) {
763 if (adev->active_input->enable_aec) {
764 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
765 snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
766 } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
767 snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
768 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
769 snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
770 }
771 set_echo_reference(adev->mixer, "SLIM_RX");
772 } else
773 set_echo_reference(adev->mixer, "NONE");
774 }
775 } else if (source == AUDIO_SOURCE_DEFAULT) {
776 goto exit;
777 }
778
779
780 if (snd_device != SND_DEVICE_NONE) {
781 goto exit;
782 }
783
784 if (in_device != AUDIO_DEVICE_NONE &&
785 !(in_device & AUDIO_DEVICE_IN_VOICE_CALL) &&
786 !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) {
787 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
788 snd_device = SND_DEVICE_IN_HANDSET_MIC;
789 } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
790 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
791 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
792 snd_device = SND_DEVICE_IN_HEADSET_MIC;
793 } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
794 snd_device = SND_DEVICE_IN_BT_SCO_MIC ;
795 } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) {
796 snd_device = SND_DEVICE_IN_HDMI_MIC;
797 } else {
798 ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
799 ALOGW("%s: Using default handset-mic", __func__);
800 snd_device = SND_DEVICE_IN_HANDSET_MIC;
801 }
802 } else {
803 if (out_device & AUDIO_DEVICE_OUT_EARPIECE) {
804 snd_device = SND_DEVICE_IN_HANDSET_MIC;
805 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
806 snd_device = SND_DEVICE_IN_HEADSET_MIC;
807 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
808 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
809 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
810 snd_device = SND_DEVICE_IN_HANDSET_MIC;
811 } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
812 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
813 } else if (out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
814 snd_device = SND_DEVICE_IN_HDMI_MIC;
815 } else {
816 ALOGE("%s: Unknown output device(s) %#x", __func__, out_device);
817 ALOGW("%s: Using default handset-mic", __func__);
818 snd_device = SND_DEVICE_IN_HANDSET_MIC;
819 }
820 }
821exit:
822 ALOGV("%s: exit: in_snd_device(%s)", __func__, device_table[snd_device]);
823 return snd_device;
824}
825
826int platform_set_hdmi_channels(void *platform, int channel_count)
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 *channel_cnt_str = NULL;
832 const char *mixer_ctl_name = "HDMI_RX Channels";
833 switch (channel_count) {
834 case 8:
835 channel_cnt_str = "Eight"; break;
836 case 7:
837 channel_cnt_str = "Seven"; break;
838 case 6:
839 channel_cnt_str = "Six"; break;
840 case 5:
841 channel_cnt_str = "Five"; break;
842 case 4:
843 channel_cnt_str = "Four"; break;
844 case 3:
845 channel_cnt_str = "Three"; break;
846 default:
847 channel_cnt_str = "Two"; break;
848 }
849 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
850 if (!ctl) {
851 ALOGE("%s: Could not get ctl for mixer cmd - %s",
852 __func__, mixer_ctl_name);
853 return -EINVAL;
854 }
855 ALOGV("HDMI channel count: %s", channel_cnt_str);
856 mixer_ctl_set_enum_by_string(ctl, channel_cnt_str);
857 return 0;
858}
859
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700860int platform_edid_get_max_channels(void *platform)
Eric Laurentb23d5282013-05-14 15:27:20 -0700861{
862 FILE *file;
863 struct audio_block_header header;
864 char block[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE];
865 char *sad = block;
866 int num_audio_blocks;
867 int channel_count;
868 int max_channels = 0;
869 int i;
870
871 file = fopen(AUDIO_DATA_BLOCK_PATH, "rb");
872 if (file == NULL) {
873 ALOGE("Unable to open '%s'", AUDIO_DATA_BLOCK_PATH);
874 return 0;
875 }
876
877 /* Read audio block header */
878 fread(&header, 1, sizeof(header), file);
879
880 /* Read SAD blocks, clamping the maximum size for safety */
881 if (header.length > (int)sizeof(block))
882 header.length = (int)sizeof(block);
883 fread(&block, header.length, 1, file);
884
885 fclose(file);
886
887 /* Calculate the number of SAD blocks */
888 num_audio_blocks = header.length / SAD_BLOCK_SIZE;
889
890 for (i = 0; i < num_audio_blocks; i++) {
891 /* Only consider LPCM blocks */
892 if ((sad[0] >> 3) != EDID_FORMAT_LPCM)
893 continue;
894
895 channel_count = (sad[0] & 0x7) + 1;
896 if (channel_count > max_channels)
897 max_channels = channel_count;
898
899 /* Advance to next block */
900 sad += 3;
901 }
902
903 return max_channels;
904}
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700905
906void platform_get_parameters(void *platform, struct str_parms *query,
907 struct str_parms *reply)
908{
909 LOGE("%s: Not implemented", __func__);
910}
911
912int platform_set_parameters(void *platform, struct str_parms *parms)
913{
914 LOGE("%s: Not implemented", __func__);
915 return -ENOSYS;
916}
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700917
918int platform_set_incall_recoding_session_id(void *platform, uint32_t session_id)
919{
920 LOGE("%s: Not implemented", __func__);
921 return -ENOSYS;
922}
Shruthi Krishnaace10852013-10-25 14:32:12 -0700923
Haynes Mathew George7ff216f2013-09-11 19:51:41 -0700924/* Delay in Us */
925int64_t platform_render_latency(audio_usecase_t usecase)
926{
927 switch (usecase) {
928 case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER:
929 return DEEP_BUFFER_PLATFORM_DELAY;
930 case USECASE_AUDIO_PLAYBACK_LOW_LATENCY:
931 return LOW_LATENCY_PLATFORM_DELAY;
932 default:
933 return 0;
934 }
935}