blob: bb732f60e25ca274343232a232975cc688681bad [file] [log] [blame]
Eric Laurentb23d5282013-05-14 15:27:20 -07001/*
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -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 "msm8974_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>
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070028#include <cutils/str_parms.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070029#include <audio_hw.h>
30#include <platform_api.h>
31#include "platform.h"
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070032#include "audio_extn.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070033
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -070034#define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
Eric Laurentb23d5282013-05-14 15:27:20 -070035#define LIB_ACDB_LOADER "libacdbloader.so"
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -070036#define AUDIO_DATA_BLOCK_MIXER_CTL "HDMI EDID"
Eric Laurentb23d5282013-05-14 15:27:20 -070037
Eric Laurentb23d5282013-05-14 15:27:20 -070038/*
Eric Laurentb23d5282013-05-14 15:27:20 -070039 * This file will have a maximum of 38 bytes:
40 *
41 * 4 bytes: number of audio blocks
42 * 4 bytes: total length of Short Audio Descriptor (SAD) blocks
43 * Maximum 10 * 3 bytes: SAD blocks
44 */
45#define MAX_SAD_BLOCKS 10
46#define SAD_BLOCK_SIZE 3
47
48/* EDID format ID for LPCM audio */
49#define EDID_FORMAT_LPCM 1
50
sangwoo1b9f4b32013-06-21 18:22:55 -070051/* Retry for delay in FW loading*/
52#define RETRY_NUMBER 10
53#define RETRY_US 500000
54
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070055#define SAMPLE_RATE_8KHZ 8000
56#define SAMPLE_RATE_16KHZ 16000
57
sangwoo53b2cf02013-07-25 19:18:44 -070058#define MAX_VOL_INDEX 5
59#define MIN_VOL_INDEX 0
60#define percent_to_index(val, min, max) \
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070061 ((val) * ((max) - (min)) * 0.01 + (min) + .5)
62
63#define AUDIO_PARAMETER_KEY_FLUENCE_TYPE "fluence"
64#define AUDIO_PARAMETER_KEY_BTSCO "bt_samplerate"
65#define AUDIO_PARAMETER_KEY_SLOWTALK "st_enable"
sangwoo53b2cf02013-07-25 19:18:44 -070066
Eric Laurentb23d5282013-05-14 15:27:20 -070067struct audio_block_header
68{
69 int reserved;
70 int length;
71};
72
73typedef void (*acdb_deallocate_t)();
74typedef int (*acdb_init_t)();
75typedef void (*acdb_send_audio_cal_t)(int, int);
76typedef void (*acdb_send_voice_cal_t)(int, int);
77
78/* Audio calibration related functions */
79struct platform_data {
80 struct audio_device *adev;
81 bool fluence_in_spkr_mode;
82 bool fluence_in_voice_call;
83 bool fluence_in_voice_rec;
Mingming Yin8e5a4f62013-10-07 15:23:41 -070084 int fluence_type;
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070085 int btsco_sample_rate;
86 bool slowtalk;
Eric Laurentb23d5282013-05-14 15:27:20 -070087
88 void *acdb_handle;
89 acdb_init_t acdb_init;
90 acdb_deallocate_t acdb_deallocate;
91 acdb_send_audio_cal_t acdb_send_audio_cal;
92 acdb_send_voice_cal_t acdb_send_voice_cal;
93};
94
95static const int pcm_device_table[AUDIO_USECASE_MAX][2] = {
Mingming Yin8e5a4f62013-10-07 15:23:41 -070096 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {DEEP_BUFFER_PCM_DEVICE,
97 DEEP_BUFFER_PCM_DEVICE},
98 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
99 LOWLATENCY_PCM_DEVICE},
100 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {MULTI_CHANNEL_PCM_DEVICE,
101 MULTI_CHANNEL_PCM_DEVICE},
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700102 [USECASE_AUDIO_RECORD] = {AUDIO_RECORD_PCM_DEVICE, AUDIO_RECORD_PCM_DEVICE},
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700103 [USECASE_AUDIO_RECORD_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
104 LOWLATENCY_PCM_DEVICE},
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700105 [USECASE_AUDIO_PLAYBACK_FM] = {FM_PLAYBACK_PCM_DEVICE, FM_CAPTURE_PCM_DEVICE},
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700106 [USECASE_VOICE_CALL] = {VOICE_CALL_PCM_DEVICE, VOICE_CALL_PCM_DEVICE},
107 [USECASE_VOICE2_CALL] = {VOICE2_CALL_PCM_DEVICE, VOICE2_CALL_PCM_DEVICE},
108 [USECASE_VOLTE_CALL] = {VOLTE_CALL_PCM_DEVICE, VOLTE_CALL_PCM_DEVICE},
109 [USECASE_QCHAT_CALL] = {QCHAT_CALL_PCM_DEVICE, QCHAT_CALL_PCM_DEVICE},
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700110 [USECASE_INCALL_REC_UPLINK] = {AUDIO_RECORD_PCM_DEVICE,
111 AUDIO_RECORD_PCM_DEVICE},
112 [USECASE_INCALL_REC_DOWNLINK] = {AUDIO_RECORD_PCM_DEVICE,
113 AUDIO_RECORD_PCM_DEVICE},
114 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = {AUDIO_RECORD_PCM_DEVICE,
115 AUDIO_RECORD_PCM_DEVICE},
Eric Laurentb23d5282013-05-14 15:27:20 -0700116};
117
118/* Array to store sound devices */
119static const char * const device_table[SND_DEVICE_MAX] = {
120 [SND_DEVICE_NONE] = "none",
121 /* Playback sound devices */
122 [SND_DEVICE_OUT_HANDSET] = "handset",
123 [SND_DEVICE_OUT_SPEAKER] = "speaker",
124 [SND_DEVICE_OUT_SPEAKER_REVERSE] = "speaker-reverse",
125 [SND_DEVICE_OUT_HEADPHONES] = "headphones",
126 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones",
127 [SND_DEVICE_OUT_VOICE_HANDSET] = "voice-handset",
128 [SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker",
129 [SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones",
130 [SND_DEVICE_OUT_HDMI] = "hdmi",
131 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
132 [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700133 [SND_DEVICE_OUT_BT_SCO_WB] = "bt-sco-headset-wb",
Eric Laurentb23d5282013-05-14 15:27:20 -0700134 [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = "voice-handset-tmus",
135 [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = "voice-tty-full-headphones",
136 [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = "voice-tty-vco-headphones",
137 [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = "voice-tty-hco-handset",
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700138 [SND_DEVICE_OUT_AFE_PROXY] = "afe-proxy",
139 [SND_DEVICE_OUT_USB_HEADSET] = "usb-headphones",
140 [SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET] = "speaker-and-usb-headphones",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700141 [SND_DEVICE_OUT_TRANSMISSION_FM] = "transmission-fm",
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700142 [SND_DEVICE_OUT_ANC_HEADSET] = "anc-headphones",
143 [SND_DEVICE_OUT_ANC_FB_HEADSET] = "anc-fb-headphones",
144 [SND_DEVICE_OUT_VOICE_ANC_HEADSET] = "voice-anc-headphones",
145 [SND_DEVICE_OUT_VOICE_ANC_FB_HEADSET] = "voice-anc-fb-headphones",
146 [SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET] = "speaker-and-anc-headphones",
147 [SND_DEVICE_OUT_ANC_HANDSET] = "anc-handset",
Eric Laurentb23d5282013-05-14 15:27:20 -0700148
149 /* Capture sound devices */
150 [SND_DEVICE_IN_HANDSET_MIC] = "handset-mic",
151 [SND_DEVICE_IN_SPEAKER_MIC] = "speaker-mic",
152 [SND_DEVICE_IN_HEADSET_MIC] = "headset-mic",
153 [SND_DEVICE_IN_HANDSET_MIC_AEC] = "handset-mic",
154 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = "voice-speaker-mic",
155 [SND_DEVICE_IN_HEADSET_MIC_AEC] = "headset-mic",
156 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "voice-speaker-mic",
157 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "voice-headset-mic",
158 [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic",
159 [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700160 [SND_DEVICE_IN_BT_SCO_MIC_WB] = "bt-sco-mic-wb",
Eric Laurentb23d5282013-05-14 15:27:20 -0700161 [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic",
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700162 [SND_DEVICE_IN_VOICE_DMIC] = "voice-dmic-ef",
163 [SND_DEVICE_IN_VOICE_DMIC_TMUS] = "voice-dmic-ef-tmus",
164 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC] = "voice-speaker-dmic-ef",
Eric Laurentb23d5282013-05-14 15:27:20 -0700165 [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = "voice-tty-full-headset-mic",
166 [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = "voice-tty-vco-handset-mic",
167 [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = "voice-tty-hco-headset-mic",
168 [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic",
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700169 [SND_DEVICE_IN_VOICE_REC_DMIC] = "voice-rec-dmic-ef",
170 [SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE] = "voice-rec-dmic-ef-fluence",
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700171 [SND_DEVICE_IN_USB_HEADSET_MIC] = "usb-headset-mic",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700172 [SND_DEVICE_IN_CAPTURE_FM] = "capture-fm",
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700173 [SND_DEVICE_IN_AANC_HANDSET_MIC] = "aanc-handset-mic",
Eric Laurentb23d5282013-05-14 15:27:20 -0700174};
175
176/* ACDB IDs (audio DSP path configuration IDs) for each sound device */
177static const int acdb_device_table[SND_DEVICE_MAX] = {
178 [SND_DEVICE_NONE] = -1,
179 [SND_DEVICE_OUT_HANDSET] = 7,
180 [SND_DEVICE_OUT_SPEAKER] = 15,
181 [SND_DEVICE_OUT_SPEAKER_REVERSE] = 15,
182 [SND_DEVICE_OUT_HEADPHONES] = 10,
183 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = 10,
184 [SND_DEVICE_OUT_VOICE_HANDSET] = 7,
185 [SND_DEVICE_OUT_VOICE_SPEAKER] = 15,
186 [SND_DEVICE_OUT_VOICE_HEADPHONES] = 10,
187 [SND_DEVICE_OUT_HDMI] = 18,
188 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 15,
189 [SND_DEVICE_OUT_BT_SCO] = 22,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700190 [SND_DEVICE_OUT_BT_SCO_WB] = 39,
sangwooc69476f2013-07-26 16:57:26 -0700191 [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = 88,
Eric Laurentb23d5282013-05-14 15:27:20 -0700192 [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = 17,
193 [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = 17,
194 [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = 37,
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700195 [SND_DEVICE_OUT_AFE_PROXY] = 0,
196 [SND_DEVICE_OUT_USB_HEADSET] = 0,
197 [SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET] = 14,
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700198 [SND_DEVICE_OUT_TRANSMISSION_FM] = 0,
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700199 [SND_DEVICE_OUT_ANC_HEADSET] = 26,
200 [SND_DEVICE_OUT_ANC_FB_HEADSET] = 26,
201 [SND_DEVICE_OUT_VOICE_ANC_HEADSET] = 26,
202 [SND_DEVICE_OUT_VOICE_ANC_FB_HEADSET] = 26,
203 [SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET] = 26,
204 [SND_DEVICE_OUT_ANC_HANDSET] = 103,
Eric Laurentb23d5282013-05-14 15:27:20 -0700205
206 [SND_DEVICE_IN_HANDSET_MIC] = 4,
207 [SND_DEVICE_IN_SPEAKER_MIC] = 4, /* ToDo: Check if this needs to changed to 11 */
208 [SND_DEVICE_IN_HEADSET_MIC] = 8,
209 [SND_DEVICE_IN_HANDSET_MIC_AEC] = 40,
210 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = 42,
211 [SND_DEVICE_IN_HEADSET_MIC_AEC] = 47,
212 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = 11,
213 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = 8,
214 [SND_DEVICE_IN_HDMI_MIC] = 4,
215 [SND_DEVICE_IN_BT_SCO_MIC] = 21,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700216 [SND_DEVICE_IN_BT_SCO_MIC_WB] = 38,
Eric Laurentb23d5282013-05-14 15:27:20 -0700217 [SND_DEVICE_IN_CAMCORDER_MIC] = 61,
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700218 [SND_DEVICE_IN_VOICE_DMIC] = 41,
219 [SND_DEVICE_IN_VOICE_DMIC_TMUS] = 89,
220 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC] = 43,
Eric Laurentb23d5282013-05-14 15:27:20 -0700221 [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = 16,
222 [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = 36,
223 [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = 16,
224 [SND_DEVICE_IN_VOICE_REC_MIC] = 62,
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700225 [SND_DEVICE_IN_USB_HEADSET_MIC] = 44,
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700226 [SND_DEVICE_IN_CAPTURE_FM] = 0,
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700227 [SND_DEVICE_IN_AANC_HANDSET_MIC] = 104,
Eric Laurentb23d5282013-05-14 15:27:20 -0700228 /* TODO: Update with proper acdb ids */
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700229 [SND_DEVICE_IN_VOICE_REC_DMIC] = 62,
230 [SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE] = 6,
Eric Laurentb23d5282013-05-14 15:27:20 -0700231};
232
233static pthread_once_t check_op_once_ctl = PTHREAD_ONCE_INIT;
234static bool is_tmus = false;
235
236static void check_operator()
237{
238 char value[PROPERTY_VALUE_MAX];
239 int mccmnc;
240 property_get("gsm.sim.operator.numeric",value,"0");
241 mccmnc = atoi(value);
242 ALOGD("%s: tmus mccmnc %d", __func__, mccmnc);
243 switch(mccmnc) {
244 /* TMUS MCC(310), MNC(490, 260, 026) */
245 case 310490:
246 case 310260:
247 case 310026:
248 is_tmus = true;
249 break;
250 }
251}
252
253bool is_operator_tmus()
254{
255 pthread_once(&check_op_once_ctl, check_operator);
256 return is_tmus;
257}
258
259static int set_echo_reference(struct mixer *mixer, const char* ec_ref)
260{
261 struct mixer_ctl *ctl;
262 const char *mixer_ctl_name = "EC_REF_RX";
263
264 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
265 if (!ctl) {
266 ALOGE("%s: Could not get ctl for mixer cmd - %s",
267 __func__, mixer_ctl_name);
268 return -EINVAL;
269 }
270 ALOGV("Setting EC Reference: %s", ec_ref);
271 mixer_ctl_set_enum_by_string(ctl, ec_ref);
272 return 0;
273}
274
275void *platform_init(struct audio_device *adev)
276{
277 char value[PROPERTY_VALUE_MAX];
278 struct platform_data *my_data;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700279 int retry_num = 0, ret;
sangwoo1b9f4b32013-06-21 18:22:55 -0700280
281 adev->mixer = mixer_open(MIXER_CARD);
282
283 while (!adev->mixer && retry_num < RETRY_NUMBER) {
284 usleep(RETRY_US);
285 adev->mixer = mixer_open(MIXER_CARD);
286 retry_num++;
287 }
288
289 if (!adev->mixer) {
290 ALOGE("Unable to open the mixer, aborting.");
291 return NULL;
292 }
293
294 adev->audio_route = audio_route_init(MIXER_CARD, MIXER_XML_PATH);
295 if (!adev->audio_route) {
296 ALOGE("%s: Failed to init audio route controls, aborting.", __func__);
297 return NULL;
298 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700299
300 my_data = calloc(1, sizeof(struct platform_data));
301
302 my_data->adev = adev;
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700303 my_data->btsco_sample_rate = SAMPLE_RATE_8KHZ;
Eric Laurentb23d5282013-05-14 15:27:20 -0700304 my_data->fluence_in_spkr_mode = false;
305 my_data->fluence_in_voice_call = false;
306 my_data->fluence_in_voice_rec = false;
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700307 my_data->fluence_type = FLUENCE_NONE;
Eric Laurentb23d5282013-05-14 15:27:20 -0700308
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700309 property_get("ro.qc.sdk.audio.fluencetype", value, "");
310 if (!strncmp("fluencepro", value, sizeof("fluencepro"))) {
311 my_data->fluence_type = FLUENCE_QUAD_MIC;
312 } else if (!strncmp("fluence", value, sizeof("fluence"))) {
313 my_data->fluence_type = FLUENCE_DUAL_MIC;
314 } else {
315 my_data->fluence_type = FLUENCE_NONE;
Eric Laurentb23d5282013-05-14 15:27:20 -0700316 }
317
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700318 if (my_data->fluence_type != FLUENCE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700319 property_get("persist.audio.fluence.voicecall",value,"");
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700320 if (!strncmp("true", value, sizeof("true"))) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700321 my_data->fluence_in_voice_call = true;
322 }
323
324 property_get("persist.audio.fluence.voicerec",value,"");
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700325 if (!strncmp("true", value, sizeof("true"))) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700326 my_data->fluence_in_voice_rec = true;
327 }
328
329 property_get("persist.audio.fluence.speaker",value,"");
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700330 if (!strncmp("true", value, sizeof("true"))) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700331 my_data->fluence_in_spkr_mode = true;
332 }
333 }
334
335 my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
336 if (my_data->acdb_handle == NULL) {
337 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_ACDB_LOADER);
338 } else {
339 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_ACDB_LOADER);
340 my_data->acdb_deallocate = (acdb_deallocate_t)dlsym(my_data->acdb_handle,
341 "acdb_loader_deallocate_ACDB");
342 my_data->acdb_send_audio_cal = (acdb_send_audio_cal_t)dlsym(my_data->acdb_handle,
343 "acdb_loader_send_audio_cal");
344 if (!my_data->acdb_send_audio_cal)
345 ALOGW("%s: Could not find the symbol acdb_send_audio_cal from %s",
346 __func__, LIB_ACDB_LOADER);
347 my_data->acdb_send_voice_cal = (acdb_send_voice_cal_t)dlsym(my_data->acdb_handle,
348 "acdb_loader_send_voice_cal");
349 my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
350 "acdb_loader_init_ACDB");
351 if (my_data->acdb_init == NULL)
352 ALOGE("%s: dlsym error %s for acdb_loader_init_ACDB", __func__, dlerror());
353 else
354 my_data->acdb_init();
355 }
356
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700357 /* init usb */
358 audio_extn_usb_init(adev);
359
Eric Laurentb23d5282013-05-14 15:27:20 -0700360 return my_data;
361}
362
363void platform_deinit(void *platform)
364{
365 free(platform);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700366 /* deinit usb */
367 audio_extn_usb_deinit();
Eric Laurentb23d5282013-05-14 15:27:20 -0700368}
369
370const char *platform_get_snd_device_name(snd_device_t snd_device)
371{
372 if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX)
373 return device_table[snd_device];
374 else
375 return "";
376}
377
378void platform_add_backend_name(char *mixer_path, snd_device_t snd_device)
379{
380 if (snd_device == SND_DEVICE_IN_BT_SCO_MIC)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700381 strlcat(mixer_path, " bt-sco", MIXER_PATH_MAX_LENGTH);
382 else if (snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB)
383 strlcat(mixer_path, " bt-sco-wb", MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700384 else if(snd_device == SND_DEVICE_OUT_BT_SCO)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700385 strlcat(mixer_path, " bt-sco", MIXER_PATH_MAX_LENGTH);
386 else if(snd_device == SND_DEVICE_OUT_BT_SCO_WB)
387 strlcat(mixer_path, " bt-sco-wb", MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700388 else if (snd_device == SND_DEVICE_OUT_HDMI)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700389 strlcat(mixer_path, " hdmi", MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700390 else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HDMI)
391 strcat(mixer_path, " speaker-and-hdmi");
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700392 else if (snd_device == SND_DEVICE_OUT_AFE_PROXY)
393 strlcat(mixer_path, " afe-proxy", MIXER_PATH_MAX_LENGTH);
394 else if (snd_device == SND_DEVICE_OUT_USB_HEADSET)
395 strlcat(mixer_path, " usb-headphones", MIXER_PATH_MAX_LENGTH);
396 else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET)
397 strlcat(mixer_path, " speaker-and-usb-headphones",
398 MIXER_PATH_MAX_LENGTH);
399 else if (snd_device == SND_DEVICE_IN_USB_HEADSET_MIC)
400 strlcat(mixer_path, " usb-headset-mic", MIXER_PATH_MAX_LENGTH);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700401 else if (snd_device == SND_DEVICE_IN_CAPTURE_FM)
402 strlcat(mixer_path, " capture-fm", MIXER_PATH_MAX_LENGTH);
403 else if (snd_device == SND_DEVICE_OUT_TRANSMISSION_FM)
404 strlcat(mixer_path, " transmission-fm", MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700405}
406
407int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type)
408{
409 int device_id;
410 if (device_type == PCM_PLAYBACK)
411 device_id = pcm_device_table[usecase][0];
412 else
413 device_id = pcm_device_table[usecase][1];
414 return device_id;
415}
416
417int platform_send_audio_calibration(void *platform, snd_device_t snd_device)
418{
419 struct platform_data *my_data = (struct platform_data *)platform;
420 int acdb_dev_id, acdb_dev_type;
421
422 acdb_dev_id = acdb_device_table[snd_device];
423 if (acdb_dev_id < 0) {
424 ALOGE("%s: Could not find acdb id for device(%d)",
425 __func__, snd_device);
426 return -EINVAL;
427 }
428 if (my_data->acdb_send_audio_cal) {
Eric Laurent994a6932013-07-17 11:51:42 -0700429 ("%s: sending audio calibration for snd_device(%d) acdb_id(%d)",
Eric Laurentb23d5282013-05-14 15:27:20 -0700430 __func__, snd_device, acdb_dev_id);
431 if (snd_device >= SND_DEVICE_OUT_BEGIN &&
432 snd_device < SND_DEVICE_OUT_END)
433 acdb_dev_type = ACDB_DEV_TYPE_OUT;
434 else
435 acdb_dev_type = ACDB_DEV_TYPE_IN;
436 my_data->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type);
437 }
438 return 0;
439}
440
441int platform_switch_voice_call_device_pre(void *platform)
442{
443 return 0;
444}
445
446int platform_switch_voice_call_device_post(void *platform,
447 snd_device_t out_snd_device,
448 snd_device_t in_snd_device)
449{
450 struct platform_data *my_data = (struct platform_data *)platform;
451 int acdb_rx_id, acdb_tx_id;
452
453 if (my_data->acdb_send_voice_cal == NULL) {
454 ALOGE("%s: dlsym error for acdb_send_voice_call", __func__);
455 } else {
456 acdb_rx_id = acdb_device_table[out_snd_device];
457 acdb_tx_id = acdb_device_table[in_snd_device];
458
459 if (acdb_rx_id > 0 && acdb_tx_id > 0)
460 my_data->acdb_send_voice_cal(acdb_rx_id, acdb_tx_id);
461 else
462 ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__,
463 acdb_rx_id, acdb_tx_id);
464 }
465
466 return 0;
467}
468
469int platform_start_voice_call(void *platform)
470{
471 return 0;
472}
473
474int platform_stop_voice_call(void *platform)
475{
476 return 0;
477}
478
479int platform_set_voice_volume(void *platform, int volume)
480{
481 struct platform_data *my_data = (struct platform_data *)platform;
482 struct audio_device *adev = my_data->adev;
483 struct mixer_ctl *ctl;
sangwoo53b2cf02013-07-25 19:18:44 -0700484 const char *mixer_ctl_name = "Voice Rx Gain";
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700485 int vol_index = 0;
486 uint32_t set_values[ ] = {0,
487 ALL_SESSION_VSID,
488 DEFAULT_VOLUME_RAMP_DURATION_MS};
Eric Laurentb23d5282013-05-14 15:27:20 -0700489
490 // Voice volume levels are mapped to adsp volume levels as follows.
491 // 100 -> 5, 80 -> 4, 60 -> 3, 40 -> 2, 20 -> 1 0 -> 0
492 // But this values don't changed in kernel. So, below change is need.
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700493 vol_index = (int)percent_to_index(volume, MIN_VOL_INDEX, MAX_VOL_INDEX);
494 set_values[0] = vol_index;
Eric Laurentb23d5282013-05-14 15:27:20 -0700495
496 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
497 if (!ctl) {
498 ALOGE("%s: Could not get ctl for mixer cmd - %s",
499 __func__, mixer_ctl_name);
500 return -EINVAL;
501 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700502 ALOGV("Setting voice volume index: %d", set_values[0]);
503 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
Eric Laurentb23d5282013-05-14 15:27:20 -0700504
505 return 0;
506}
507
508int platform_set_mic_mute(void *platform, bool state)
509{
510 struct platform_data *my_data = (struct platform_data *)platform;
511 struct audio_device *adev = my_data->adev;
512 struct mixer_ctl *ctl;
513 const char *mixer_ctl_name = "Voice Tx Mute";
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700514 uint32_t set_values[ ] = {0,
515 ALL_SESSION_VSID,
516 DEFAULT_VOLUME_RAMP_DURATION_MS};
Eric Laurentb23d5282013-05-14 15:27:20 -0700517
518 if (adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700519 set_values[0] = state;
Eric Laurentb23d5282013-05-14 15:27:20 -0700520 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
521 if (!ctl) {
522 ALOGE("%s: Could not get ctl for mixer cmd - %s",
523 __func__, mixer_ctl_name);
524 return -EINVAL;
525 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700526 ALOGV("Setting voice mute state: %d", state);
527 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
Eric Laurentb23d5282013-05-14 15:27:20 -0700528 }
529
530 return 0;
531}
532
533snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices)
534{
535 struct platform_data *my_data = (struct platform_data *)platform;
536 struct audio_device *adev = my_data->adev;
537 audio_mode_t mode = adev->mode;
538 snd_device_t snd_device = SND_DEVICE_NONE;
539
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700540 audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
541 AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
542 int channel_count = popcount(channel_mask);
543
Eric Laurentb23d5282013-05-14 15:27:20 -0700544 ALOGV("%s: enter: output devices(%#x)", __func__, devices);
545 if (devices == AUDIO_DEVICE_NONE ||
546 devices & AUDIO_DEVICE_BIT_IN) {
547 ALOGV("%s: Invalid output devices (%#x)", __func__, devices);
548 goto exit;
549 }
550
551 if (mode == AUDIO_MODE_IN_CALL) {
552 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
553 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700554 if (adev->voice.tty_mode == TTY_MODE_FULL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700555 snd_device = SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES;
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700556 } else if (adev->voice.tty_mode == TTY_MODE_VCO) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700557 snd_device = SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES;
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700558 } else if (adev->voice.tty_mode == TTY_MODE_HCO) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700559 snd_device = SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET;
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700560 } else if (audio_extn_get_anc_enabled()) {
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700561 if (audio_extn_should_use_fb_anc())
562 snd_device = SND_DEVICE_OUT_VOICE_ANC_FB_HEADSET;
563 else
564 snd_device = SND_DEVICE_OUT_VOICE_ANC_HEADSET;
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700565 } else {
Eric Laurentb23d5282013-05-14 15:27:20 -0700566 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES;
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700567 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700568 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700569 if (my_data->btsco_sample_rate == SAMPLE_RATE_16KHZ)
570 snd_device = SND_DEVICE_OUT_BT_SCO_WB;
571 else
572 snd_device = SND_DEVICE_OUT_BT_SCO;
Eric Laurentb23d5282013-05-14 15:27:20 -0700573 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
574 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700575 } else if (devices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
576 devices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) {
577 snd_device = SND_DEVICE_OUT_USB_HEADSET;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700578 } else if (devices & AUDIO_DEVICE_OUT_FM_TX) {
579 snd_device = SND_DEVICE_OUT_TRANSMISSION_FM;
Eric Laurentb23d5282013-05-14 15:27:20 -0700580 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
581 if (is_operator_tmus())
582 snd_device = SND_DEVICE_OUT_VOICE_HANDSET_TMUS;
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700583 else if (audio_extn_should_use_handset_anc(channel_count))
584 snd_device = SND_DEVICE_OUT_ANC_HANDSET;
Eric Laurentb23d5282013-05-14 15:27:20 -0700585 else
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700586 snd_device = SND_DEVICE_OUT_VOICE_HANDSET;
Eric Laurentb23d5282013-05-14 15:27:20 -0700587 }
588 if (snd_device != SND_DEVICE_NONE) {
589 goto exit;
590 }
591 }
592
593 if (popcount(devices) == 2) {
594 if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
595 AUDIO_DEVICE_OUT_SPEAKER)) {
596 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
597 } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
598 AUDIO_DEVICE_OUT_SPEAKER)) {
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700599 if (audio_extn_get_anc_enabled())
600 snd_device = SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET;
601 else
602 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
Eric Laurentb23d5282013-05-14 15:27:20 -0700603 } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL |
604 AUDIO_DEVICE_OUT_SPEAKER)) {
605 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700606 } else if (devices == (AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
607 AUDIO_DEVICE_OUT_SPEAKER)) {
608 snd_device = SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET;
Eric Laurentb23d5282013-05-14 15:27:20 -0700609 } else {
610 ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
611 goto exit;
612 }
613 if (snd_device != SND_DEVICE_NONE) {
614 goto exit;
615 }
616 }
617
618 if (popcount(devices) != 1) {
619 ALOGE("%s: Invalid output devices(%#x)", __func__, devices);
620 goto exit;
621 }
622
623 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
624 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700625 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADSET
626 && audio_extn_get_anc_enabled()) {
627 if (audio_extn_should_use_fb_anc())
628 snd_device = SND_DEVICE_OUT_ANC_FB_HEADSET;
629 else
630 snd_device = SND_DEVICE_OUT_ANC_HEADSET;
631 }
632 else
633 snd_device = SND_DEVICE_OUT_HEADPHONES;
Eric Laurentb23d5282013-05-14 15:27:20 -0700634 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
635 if (adev->speaker_lr_swap)
636 snd_device = SND_DEVICE_OUT_SPEAKER_REVERSE;
637 else
638 snd_device = SND_DEVICE_OUT_SPEAKER;
639 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700640 if (my_data->btsco_sample_rate == SAMPLE_RATE_16KHZ)
641 snd_device = SND_DEVICE_OUT_BT_SCO_WB;
642 else
643 snd_device = SND_DEVICE_OUT_BT_SCO;
Eric Laurentb23d5282013-05-14 15:27:20 -0700644 } else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
645 snd_device = SND_DEVICE_OUT_HDMI ;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700646 } else if (devices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
647 devices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) {
648 snd_device = SND_DEVICE_OUT_USB_HEADSET;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700649 } else if (devices & AUDIO_DEVICE_OUT_FM_TX) {
650 snd_device = SND_DEVICE_OUT_TRANSMISSION_FM;
Eric Laurentb23d5282013-05-14 15:27:20 -0700651 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
652 snd_device = SND_DEVICE_OUT_HANDSET;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700653 } else if (devices & AUDIO_DEVICE_OUT_PROXY) {
654 ALOGD("%s: setting sink capability for Proxy", __func__);
655 audio_extn_set_afe_proxy_channel_mixer(adev);
656 snd_device = SND_DEVICE_OUT_AFE_PROXY;
Eric Laurentb23d5282013-05-14 15:27:20 -0700657 } else {
658 ALOGE("%s: Unknown device(s) %#x", __func__, devices);
659 }
660exit:
661 ALOGV("%s: exit: snd_device(%s)", __func__, device_table[snd_device]);
662 return snd_device;
663}
664
665snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device)
666{
667 struct platform_data *my_data = (struct platform_data *)platform;
668 struct audio_device *adev = my_data->adev;
669 audio_source_t source = (adev->active_input == NULL) ?
670 AUDIO_SOURCE_DEFAULT : adev->active_input->source;
671
672 audio_mode_t mode = adev->mode;
673 audio_devices_t in_device = ((adev->active_input == NULL) ?
674 AUDIO_DEVICE_NONE : adev->active_input->device)
675 & ~AUDIO_DEVICE_BIT_IN;
676 audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
677 AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
678 snd_device_t snd_device = SND_DEVICE_NONE;
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700679 int channel_count = popcount(channel_mask);
Eric Laurentb23d5282013-05-14 15:27:20 -0700680
681 ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
682 __func__, out_device, in_device);
683 if (mode == AUDIO_MODE_IN_CALL) {
684 if (out_device == AUDIO_DEVICE_NONE) {
685 ALOGE("%s: No output device set for voice call", __func__);
686 goto exit;
687 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700688 if (adev->voice.tty_mode != TTY_MODE_OFF) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700689 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
690 out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700691 switch (adev->voice.tty_mode) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700692 case TTY_MODE_FULL:
693 snd_device = SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC;
694 break;
695 case TTY_MODE_VCO:
696 snd_device = SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC;
697 break;
698 case TTY_MODE_HCO:
699 snd_device = SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC;
700 break;
701 default:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700702 ALOGE("%s: Invalid TTY mode (%#x)",
703 __func__, adev->voice.tty_mode);
Eric Laurentb23d5282013-05-14 15:27:20 -0700704 }
705 goto exit;
706 }
707 }
708 if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
709 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700710 if (out_device & AUDIO_DEVICE_OUT_EARPIECE &&
711 audio_extn_should_use_handset_anc(channel_count)) {
712 snd_device = SND_DEVICE_IN_AANC_HANDSET_MIC;
713 } else if (my_data->fluence_type == FLUENCE_NONE ||
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700714 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) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700726 if (my_data->btsco_sample_rate == SAMPLE_RATE_16KHZ)
727 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
728 else
729 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
Eric Laurentb23d5282013-05-14 15:27:20 -0700730 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700731 if (my_data->fluence_type != FLUENCE_NONE &&
732 my_data->fluence_in_voice_call &&
733 my_data->fluence_in_spkr_mode) {
734 if(my_data->fluence_type == FLUENCE_DUAL_MIC) {
735 adev->acdb_settings |= DMIC_FLAG;
736 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC;
737 } else {
738 adev->acdb_settings |= QMIC_FLAG;
739 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_QMIC;
740 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700741 } else {
742 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
743 }
744 }
745 } else if (source == AUDIO_SOURCE_CAMCORDER) {
746 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
747 in_device & AUDIO_DEVICE_IN_BACK_MIC) {
748 snd_device = SND_DEVICE_IN_CAMCORDER_MIC;
749 }
750 } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) {
751 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700752 if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
753 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC;
754 else if (my_data->fluence_in_voice_rec)
755 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE;
Eric Laurentb23d5282013-05-14 15:27:20 -0700756
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700757 if (snd_device == SND_DEVICE_NONE)
Eric Laurentb23d5282013-05-14 15:27:20 -0700758 snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700759 else
760 adev->acdb_settings |= DMIC_FLAG;
Eric Laurentb23d5282013-05-14 15:27:20 -0700761 }
762 } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
763 if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
764 in_device = AUDIO_DEVICE_IN_BACK_MIC;
765 if (adev->active_input) {
766 if (adev->active_input->enable_aec) {
767 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
768 snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
769 } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
770 snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
771 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
772 snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
773 }
774 set_echo_reference(adev->mixer, "SLIM_RX");
775 } else
776 set_echo_reference(adev->mixer, "NONE");
777 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700778 } else if (source == AUDIO_SOURCE_FM_RX) {
779 if (in_device & AUDIO_DEVICE_IN_FM_RX) {
780 snd_device = SND_DEVICE_IN_CAPTURE_FM;
781 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700782 } else if (source == AUDIO_SOURCE_DEFAULT) {
783 goto exit;
784 }
785
786
787 if (snd_device != SND_DEVICE_NONE) {
788 goto exit;
789 }
790
791 if (in_device != AUDIO_DEVICE_NONE &&
792 !(in_device & AUDIO_DEVICE_IN_VOICE_CALL) &&
793 !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) {
794 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
795 snd_device = SND_DEVICE_IN_HANDSET_MIC;
796 } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
797 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
798 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
799 snd_device = SND_DEVICE_IN_HEADSET_MIC;
800 } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700801 if (my_data->btsco_sample_rate == SAMPLE_RATE_16KHZ)
802 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
803 else
804 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
Eric Laurentb23d5282013-05-14 15:27:20 -0700805 } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) {
806 snd_device = SND_DEVICE_IN_HDMI_MIC;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700807 } else if (in_device & AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET ||
808 in_device & AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET) {
809 snd_device = SND_DEVICE_IN_USB_HEADSET_MIC;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700810 } else if (in_device & AUDIO_DEVICE_IN_FM_RX) {
811 snd_device = SND_DEVICE_IN_CAPTURE_FM;
Eric Laurentb23d5282013-05-14 15:27:20 -0700812 } else {
813 ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
814 ALOGW("%s: Using default handset-mic", __func__);
815 snd_device = SND_DEVICE_IN_HANDSET_MIC;
816 }
817 } else {
818 if (out_device & AUDIO_DEVICE_OUT_EARPIECE) {
819 snd_device = SND_DEVICE_IN_HANDSET_MIC;
820 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
821 snd_device = SND_DEVICE_IN_HEADSET_MIC;
822 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
823 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
824 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
825 snd_device = SND_DEVICE_IN_HANDSET_MIC;
826 } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700827 if (my_data->btsco_sample_rate == SAMPLE_RATE_16KHZ)
828 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
829 else
830 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
Eric Laurentb23d5282013-05-14 15:27:20 -0700831 } else if (out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
832 snd_device = SND_DEVICE_IN_HDMI_MIC;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700833 } else if (out_device & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
834 out_device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) {
835 snd_device = SND_DEVICE_IN_USB_HEADSET_MIC;
Eric Laurentb23d5282013-05-14 15:27:20 -0700836 } else {
837 ALOGE("%s: Unknown output device(s) %#x", __func__, out_device);
838 ALOGW("%s: Using default handset-mic", __func__);
839 snd_device = SND_DEVICE_IN_HANDSET_MIC;
840 }
841 }
842exit:
843 ALOGV("%s: exit: in_snd_device(%s)", __func__, device_table[snd_device]);
844 return snd_device;
845}
846
847int platform_set_hdmi_channels(void *platform, int channel_count)
848{
849 struct platform_data *my_data = (struct platform_data *)platform;
850 struct audio_device *adev = my_data->adev;
851 struct mixer_ctl *ctl;
852 const char *channel_cnt_str = NULL;
853 const char *mixer_ctl_name = "HDMI_RX Channels";
854 switch (channel_count) {
855 case 8:
856 channel_cnt_str = "Eight"; break;
857 case 7:
858 channel_cnt_str = "Seven"; break;
859 case 6:
860 channel_cnt_str = "Six"; break;
861 case 5:
862 channel_cnt_str = "Five"; break;
863 case 4:
864 channel_cnt_str = "Four"; break;
865 case 3:
866 channel_cnt_str = "Three"; break;
867 default:
868 channel_cnt_str = "Two"; break;
869 }
870 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
871 if (!ctl) {
872 ALOGE("%s: Could not get ctl for mixer cmd - %s",
873 __func__, mixer_ctl_name);
874 return -EINVAL;
875 }
876 ALOGV("HDMI channel count: %s", channel_cnt_str);
877 mixer_ctl_set_enum_by_string(ctl, channel_cnt_str);
878 return 0;
879}
880
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700881int platform_edid_get_max_channels(void *platform)
Eric Laurentb23d5282013-05-14 15:27:20 -0700882{
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700883 struct platform_data *my_data = (struct platform_data *)platform;
884 struct audio_device *adev = my_data->adev;
Eric Laurentb23d5282013-05-14 15:27:20 -0700885 char block[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE];
886 char *sad = block;
887 int num_audio_blocks;
888 int channel_count;
889 int max_channels = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700890 int i, ret, count;
Eric Laurentb23d5282013-05-14 15:27:20 -0700891
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700892 struct mixer_ctl *ctl;
893
894 ctl = mixer_get_ctl_by_name(adev->mixer, AUDIO_DATA_BLOCK_MIXER_CTL);
895 if (!ctl) {
896 ALOGE("%s: Could not get ctl for mixer cmd - %s",
897 __func__, AUDIO_DATA_BLOCK_MIXER_CTL);
Eric Laurentb23d5282013-05-14 15:27:20 -0700898 return 0;
899 }
900
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700901 mixer_ctl_update(ctl);
902
903 count = mixer_ctl_get_num_values(ctl);
Eric Laurentb23d5282013-05-14 15:27:20 -0700904
905 /* Read SAD blocks, clamping the maximum size for safety */
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700906 if (count > (int)sizeof(block))
907 count = (int)sizeof(block);
Eric Laurentb23d5282013-05-14 15:27:20 -0700908
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700909 ret = mixer_ctl_get_array(ctl, block, count);
910 if (ret != 0) {
911 ALOGE("%s: mixer_ctl_get_array() failed to get EDID info", __func__);
912 return 0;
913 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700914
915 /* Calculate the number of SAD blocks */
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700916 num_audio_blocks = count / SAD_BLOCK_SIZE;
Eric Laurentb23d5282013-05-14 15:27:20 -0700917
918 for (i = 0; i < num_audio_blocks; i++) {
919 /* Only consider LPCM blocks */
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700920 if ((sad[0] >> 3) != EDID_FORMAT_LPCM) {
921 sad += 3;
Eric Laurentb23d5282013-05-14 15:27:20 -0700922 continue;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700923 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700924
925 channel_count = (sad[0] & 0x7) + 1;
926 if (channel_count > max_channels)
927 max_channels = channel_count;
928
929 /* Advance to next block */
930 sad += 3;
931 }
932
933 return max_channels;
934}
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700935
936static int platform_set_slowtalk(struct platform_data *my_data, bool state)
937{
938 int ret = 0;
939 struct audio_device *adev = my_data->adev;
940 struct mixer_ctl *ctl;
941 const char *mixer_ctl_name = "Slowtalk Enable";
942 uint32_t set_values[ ] = {0,
943 ALL_SESSION_VSID};
944
945 set_values[0] = state;
946 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
947 if (!ctl) {
948 ALOGE("%s: Could not get ctl for mixer cmd - %s",
949 __func__, mixer_ctl_name);
950 ret = -EINVAL;
951 } else {
952 ALOGV("Setting slowtalk state: %d", state);
953 ret = mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
954 my_data->slowtalk = state;
955 }
956
957 return ret;
958}
959
960int platform_set_parameters(void *platform, struct str_parms *parms)
961{
962 struct platform_data *my_data = (struct platform_data *)platform;
963 char *str;
964 char value[32];
965 int val;
966 int ret = 0;
967
968 ALOGV("%s: enter: %s", __func__, str_parms_to_str(parms));
969
970 ret = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_BTSCO, &val);
971 if (ret >= 0) {
972 str_parms_del(parms, AUDIO_PARAMETER_KEY_BTSCO);
973 pthread_mutex_lock(&my_data->adev->lock);
974 my_data->btsco_sample_rate = val;
975 pthread_mutex_unlock(&my_data->adev->lock);
976 }
977
978 ret = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_SLOWTALK, &val);
979 if (ret >= 0) {
980 str_parms_del(parms, AUDIO_PARAMETER_KEY_SLOWTALK);
981 pthread_mutex_lock(&my_data->adev->lock);
982 ret = platform_set_slowtalk(my_data, val);
983 if (ret)
984 ALOGE("%s: Failed to set slow talk err: %d", __func__, ret);
985 pthread_mutex_unlock(&my_data->adev->lock);
986 }
987
988 ALOGV("%s: exit with code(%d)", __func__, ret);
989 return ret;
990}
991
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700992int platform_set_incall_recoding_session_id(void *platform,
993 uint32_t session_id)
994{
995 int ret = 0;
996 struct platform_data *my_data = (struct platform_data *)platform;
997 struct audio_device *adev = my_data->adev;
998 struct mixer_ctl *ctl;
999 const char *mixer_ctl_name = "Voc VSID";
1000 int num_ctl_values;
1001 int i;
1002
1003 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1004 if (!ctl) {
1005 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1006 __func__, mixer_ctl_name);
1007 ret = -EINVAL;
1008 } else {
1009 num_ctl_values = mixer_ctl_get_num_values(ctl);
1010 for (i = 0; i < num_ctl_values; i++) {
1011 if (mixer_ctl_set_value(ctl, i, session_id)) {
1012 ALOGV("Error: invalid session_id: %x", session_id);
1013 ret = -EINVAL;
1014 break;
1015 }
1016 }
1017 }
1018
1019 return ret;
1020}
1021
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001022void platform_get_parameters(void *platform,
1023 struct str_parms *query,
1024 struct str_parms *reply)
1025{
1026 struct platform_data *my_data = (struct platform_data *)platform;
1027 char *str = NULL;
1028 char value[256] = {0};
1029 int ret;
1030 int fluence_type;
1031
1032 ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_FLUENCE_TYPE,
1033 value, sizeof(value));
1034 if (ret >= 0) {
1035 pthread_mutex_lock(&my_data->adev->lock);
1036 if (my_data->fluence_type == FLUENCE_QUAD_MIC) {
1037 strlcpy(value, "fluencepro", sizeof(value));
1038 } else if (my_data->fluence_type == FLUENCE_DUAL_MIC) {
1039 strlcpy(value, "fluence", sizeof(value));
1040 } else {
1041 strlcpy(value, "none", sizeof(value));
1042 }
1043 pthread_mutex_unlock(&my_data->adev->lock);
1044
1045 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_FLUENCE_TYPE, value);
1046 }
1047
1048 ALOGV("%s: exit: returns - %s", __func__, str_parms_to_str(reply));
1049}
1050