blob: ee069d77d42c4cb7e53671b81134bebba6ce5f2d [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},
102 [USECASE_AUDIO_RECORD] = {DEEP_BUFFER_PCM_DEVICE, DEEP_BUFFER_PCM_DEVICE},
103 [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},
Eric Laurentb23d5282013-05-14 15:27:20 -0700110};
111
112/* Array to store sound devices */
113static const char * const device_table[SND_DEVICE_MAX] = {
114 [SND_DEVICE_NONE] = "none",
115 /* Playback sound devices */
116 [SND_DEVICE_OUT_HANDSET] = "handset",
117 [SND_DEVICE_OUT_SPEAKER] = "speaker",
118 [SND_DEVICE_OUT_SPEAKER_REVERSE] = "speaker-reverse",
119 [SND_DEVICE_OUT_HEADPHONES] = "headphones",
120 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones",
121 [SND_DEVICE_OUT_VOICE_HANDSET] = "voice-handset",
122 [SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker",
123 [SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones",
124 [SND_DEVICE_OUT_HDMI] = "hdmi",
125 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
126 [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700127 [SND_DEVICE_OUT_BT_SCO_WB] = "bt-sco-headset-wb",
Eric Laurentb23d5282013-05-14 15:27:20 -0700128 [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",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700132 [SND_DEVICE_OUT_TRANSMISSION_FM] = "transmission-fm",
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700133 [SND_DEVICE_OUT_ANC_HEADSET] = "anc-headphones",
134 [SND_DEVICE_OUT_ANC_FB_HEADSET] = "anc-fb-headphones",
135 [SND_DEVICE_OUT_VOICE_ANC_HEADSET] = "voice-anc-headphones",
136 [SND_DEVICE_OUT_VOICE_ANC_FB_HEADSET] = "voice-anc-fb-headphones",
137 [SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET] = "speaker-and-anc-headphones",
138 [SND_DEVICE_OUT_ANC_HANDSET] = "anc-handset",
Eric Laurentb23d5282013-05-14 15:27:20 -0700139
140 /* Capture sound devices */
141 [SND_DEVICE_IN_HANDSET_MIC] = "handset-mic",
142 [SND_DEVICE_IN_SPEAKER_MIC] = "speaker-mic",
143 [SND_DEVICE_IN_HEADSET_MIC] = "headset-mic",
144 [SND_DEVICE_IN_HANDSET_MIC_AEC] = "handset-mic",
145 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = "voice-speaker-mic",
146 [SND_DEVICE_IN_HEADSET_MIC_AEC] = "headset-mic",
147 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "voice-speaker-mic",
148 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "voice-headset-mic",
149 [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic",
150 [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700151 [SND_DEVICE_IN_BT_SCO_MIC_WB] = "bt-sco-mic-wb",
Eric Laurentb23d5282013-05-14 15:27:20 -0700152 [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic",
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700153 [SND_DEVICE_IN_VOICE_DMIC] = "voice-dmic-ef",
154 [SND_DEVICE_IN_VOICE_DMIC_TMUS] = "voice-dmic-ef-tmus",
155 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC] = "voice-speaker-dmic-ef",
Eric Laurentb23d5282013-05-14 15:27:20 -0700156 [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = "voice-tty-full-headset-mic",
157 [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = "voice-tty-vco-handset-mic",
158 [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = "voice-tty-hco-headset-mic",
159 [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic",
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700160 [SND_DEVICE_IN_VOICE_REC_DMIC] = "voice-rec-dmic-ef",
161 [SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE] = "voice-rec-dmic-ef-fluence",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700162 [SND_DEVICE_IN_CAPTURE_FM] = "capture-fm",
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700163 [SND_DEVICE_IN_AANC_HANDSET_MIC] = "aanc-handset-mic",
Eric Laurentb23d5282013-05-14 15:27:20 -0700164};
165
166/* ACDB IDs (audio DSP path configuration IDs) for each sound device */
167static const int acdb_device_table[SND_DEVICE_MAX] = {
168 [SND_DEVICE_NONE] = -1,
169 [SND_DEVICE_OUT_HANDSET] = 7,
170 [SND_DEVICE_OUT_SPEAKER] = 15,
171 [SND_DEVICE_OUT_SPEAKER_REVERSE] = 15,
172 [SND_DEVICE_OUT_HEADPHONES] = 10,
173 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = 10,
174 [SND_DEVICE_OUT_VOICE_HANDSET] = 7,
175 [SND_DEVICE_OUT_VOICE_SPEAKER] = 15,
176 [SND_DEVICE_OUT_VOICE_HEADPHONES] = 10,
177 [SND_DEVICE_OUT_HDMI] = 18,
178 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 15,
179 [SND_DEVICE_OUT_BT_SCO] = 22,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700180 [SND_DEVICE_OUT_BT_SCO_WB] = 39,
sangwooc69476f2013-07-26 16:57:26 -0700181 [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = 88,
Eric Laurentb23d5282013-05-14 15:27:20 -0700182 [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = 17,
183 [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = 17,
184 [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = 37,
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700185 [SND_DEVICE_OUT_TRANSMISSION_FM] = 0,
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700186 [SND_DEVICE_OUT_ANC_HEADSET] = 26,
187 [SND_DEVICE_OUT_ANC_FB_HEADSET] = 26,
188 [SND_DEVICE_OUT_VOICE_ANC_HEADSET] = 26,
189 [SND_DEVICE_OUT_VOICE_ANC_FB_HEADSET] = 26,
190 [SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET] = 26,
191 [SND_DEVICE_OUT_ANC_HANDSET] = 103,
Eric Laurentb23d5282013-05-14 15:27:20 -0700192
193 [SND_DEVICE_IN_HANDSET_MIC] = 4,
194 [SND_DEVICE_IN_SPEAKER_MIC] = 4, /* ToDo: Check if this needs to changed to 11 */
195 [SND_DEVICE_IN_HEADSET_MIC] = 8,
196 [SND_DEVICE_IN_HANDSET_MIC_AEC] = 40,
197 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = 42,
198 [SND_DEVICE_IN_HEADSET_MIC_AEC] = 47,
199 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = 11,
200 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = 8,
201 [SND_DEVICE_IN_HDMI_MIC] = 4,
202 [SND_DEVICE_IN_BT_SCO_MIC] = 21,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700203 [SND_DEVICE_IN_BT_SCO_MIC_WB] = 38,
Eric Laurentb23d5282013-05-14 15:27:20 -0700204 [SND_DEVICE_IN_CAMCORDER_MIC] = 61,
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700205 [SND_DEVICE_IN_VOICE_DMIC] = 41,
206 [SND_DEVICE_IN_VOICE_DMIC_TMUS] = 89,
207 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC] = 43,
Eric Laurentb23d5282013-05-14 15:27:20 -0700208 [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = 16,
209 [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = 36,
210 [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = 16,
211 [SND_DEVICE_IN_VOICE_REC_MIC] = 62,
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700212 [SND_DEVICE_IN_CAPTURE_FM] = 0,
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700213 [SND_DEVICE_IN_AANC_HANDSET_MIC] = 104,
Eric Laurentb23d5282013-05-14 15:27:20 -0700214 /* TODO: Update with proper acdb ids */
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700215 [SND_DEVICE_IN_VOICE_REC_DMIC] = 62,
216 [SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE] = 6,
Eric Laurentb23d5282013-05-14 15:27:20 -0700217};
218
219static pthread_once_t check_op_once_ctl = PTHREAD_ONCE_INIT;
220static bool is_tmus = false;
221
222static void check_operator()
223{
224 char value[PROPERTY_VALUE_MAX];
225 int mccmnc;
226 property_get("gsm.sim.operator.numeric",value,"0");
227 mccmnc = atoi(value);
228 ALOGD("%s: tmus mccmnc %d", __func__, mccmnc);
229 switch(mccmnc) {
230 /* TMUS MCC(310), MNC(490, 260, 026) */
231 case 310490:
232 case 310260:
233 case 310026:
234 is_tmus = true;
235 break;
236 }
237}
238
239bool is_operator_tmus()
240{
241 pthread_once(&check_op_once_ctl, check_operator);
242 return is_tmus;
243}
244
245static int set_echo_reference(struct mixer *mixer, const char* ec_ref)
246{
247 struct mixer_ctl *ctl;
248 const char *mixer_ctl_name = "EC_REF_RX";
249
250 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
251 if (!ctl) {
252 ALOGE("%s: Could not get ctl for mixer cmd - %s",
253 __func__, mixer_ctl_name);
254 return -EINVAL;
255 }
256 ALOGV("Setting EC Reference: %s", ec_ref);
257 mixer_ctl_set_enum_by_string(ctl, ec_ref);
258 return 0;
259}
260
261void *platform_init(struct audio_device *adev)
262{
263 char value[PROPERTY_VALUE_MAX];
264 struct platform_data *my_data;
sangwoo1b9f4b32013-06-21 18:22:55 -0700265 int retry_num = 0;
266
267 adev->mixer = mixer_open(MIXER_CARD);
268
269 while (!adev->mixer && retry_num < RETRY_NUMBER) {
270 usleep(RETRY_US);
271 adev->mixer = mixer_open(MIXER_CARD);
272 retry_num++;
273 }
274
275 if (!adev->mixer) {
276 ALOGE("Unable to open the mixer, aborting.");
277 return NULL;
278 }
279
280 adev->audio_route = audio_route_init(MIXER_CARD, MIXER_XML_PATH);
281 if (!adev->audio_route) {
282 ALOGE("%s: Failed to init audio route controls, aborting.", __func__);
283 return NULL;
284 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700285
286 my_data = calloc(1, sizeof(struct platform_data));
287
288 my_data->adev = adev;
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700289 my_data->btsco_sample_rate = SAMPLE_RATE_8KHZ;
Eric Laurentb23d5282013-05-14 15:27:20 -0700290 my_data->fluence_in_spkr_mode = false;
291 my_data->fluence_in_voice_call = false;
292 my_data->fluence_in_voice_rec = false;
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700293 my_data->fluence_type = FLUENCE_NONE;
Eric Laurentb23d5282013-05-14 15:27:20 -0700294
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700295 property_get("ro.qc.sdk.audio.fluencetype", value, "");
296 if (!strncmp("fluencepro", value, sizeof("fluencepro"))) {
297 my_data->fluence_type = FLUENCE_QUAD_MIC;
298 } else if (!strncmp("fluence", value, sizeof("fluence"))) {
299 my_data->fluence_type = FLUENCE_DUAL_MIC;
300 } else {
301 my_data->fluence_type = FLUENCE_NONE;
Eric Laurentb23d5282013-05-14 15:27:20 -0700302 }
303
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700304 if (my_data->fluence_type != FLUENCE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700305 property_get("persist.audio.fluence.voicecall",value,"");
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700306 if (!strncmp("true", value, sizeof("true"))) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700307 my_data->fluence_in_voice_call = true;
308 }
309
310 property_get("persist.audio.fluence.voicerec",value,"");
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700311 if (!strncmp("true", value, sizeof("true"))) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700312 my_data->fluence_in_voice_rec = true;
313 }
314
315 property_get("persist.audio.fluence.speaker",value,"");
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700316 if (!strncmp("true", value, sizeof("true"))) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700317 my_data->fluence_in_spkr_mode = true;
318 }
319 }
320
321 my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
322 if (my_data->acdb_handle == NULL) {
323 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_ACDB_LOADER);
324 } else {
325 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_ACDB_LOADER);
326 my_data->acdb_deallocate = (acdb_deallocate_t)dlsym(my_data->acdb_handle,
327 "acdb_loader_deallocate_ACDB");
328 my_data->acdb_send_audio_cal = (acdb_send_audio_cal_t)dlsym(my_data->acdb_handle,
329 "acdb_loader_send_audio_cal");
330 if (!my_data->acdb_send_audio_cal)
331 ALOGW("%s: Could not find the symbol acdb_send_audio_cal from %s",
332 __func__, LIB_ACDB_LOADER);
333 my_data->acdb_send_voice_cal = (acdb_send_voice_cal_t)dlsym(my_data->acdb_handle,
334 "acdb_loader_send_voice_cal");
335 my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
336 "acdb_loader_init_ACDB");
337 if (my_data->acdb_init == NULL)
338 ALOGE("%s: dlsym error %s for acdb_loader_init_ACDB", __func__, dlerror());
339 else
340 my_data->acdb_init();
341 }
342
343 return my_data;
344}
345
346void platform_deinit(void *platform)
347{
348 free(platform);
349}
350
351const char *platform_get_snd_device_name(snd_device_t snd_device)
352{
353 if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX)
354 return device_table[snd_device];
355 else
356 return "";
357}
358
359void platform_add_backend_name(char *mixer_path, snd_device_t snd_device)
360{
361 if (snd_device == SND_DEVICE_IN_BT_SCO_MIC)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700362 strlcat(mixer_path, " bt-sco", MIXER_PATH_MAX_LENGTH);
363 else if (snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB)
364 strlcat(mixer_path, " bt-sco-wb", MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700365 else if(snd_device == SND_DEVICE_OUT_BT_SCO)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700366 strlcat(mixer_path, " bt-sco", MIXER_PATH_MAX_LENGTH);
367 else if(snd_device == SND_DEVICE_OUT_BT_SCO_WB)
368 strlcat(mixer_path, " bt-sco-wb", MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700369 else if (snd_device == SND_DEVICE_OUT_HDMI)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700370 strlcat(mixer_path, " hdmi", MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700371 else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HDMI)
372 strcat(mixer_path, " speaker-and-hdmi");
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700373 else if (snd_device == SND_DEVICE_IN_CAPTURE_FM)
374 strlcat(mixer_path, " capture-fm", MIXER_PATH_MAX_LENGTH);
375 else if (snd_device == SND_DEVICE_OUT_TRANSMISSION_FM)
376 strlcat(mixer_path, " transmission-fm", MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700377}
378
379int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type)
380{
381 int device_id;
382 if (device_type == PCM_PLAYBACK)
383 device_id = pcm_device_table[usecase][0];
384 else
385 device_id = pcm_device_table[usecase][1];
386 return device_id;
387}
388
389int platform_send_audio_calibration(void *platform, snd_device_t snd_device)
390{
391 struct platform_data *my_data = (struct platform_data *)platform;
392 int acdb_dev_id, acdb_dev_type;
393
394 acdb_dev_id = acdb_device_table[snd_device];
395 if (acdb_dev_id < 0) {
396 ALOGE("%s: Could not find acdb id for device(%d)",
397 __func__, snd_device);
398 return -EINVAL;
399 }
400 if (my_data->acdb_send_audio_cal) {
Eric Laurent994a6932013-07-17 11:51:42 -0700401 ("%s: sending audio calibration for snd_device(%d) acdb_id(%d)",
Eric Laurentb23d5282013-05-14 15:27:20 -0700402 __func__, snd_device, acdb_dev_id);
403 if (snd_device >= SND_DEVICE_OUT_BEGIN &&
404 snd_device < SND_DEVICE_OUT_END)
405 acdb_dev_type = ACDB_DEV_TYPE_OUT;
406 else
407 acdb_dev_type = ACDB_DEV_TYPE_IN;
408 my_data->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type);
409 }
410 return 0;
411}
412
413int platform_switch_voice_call_device_pre(void *platform)
414{
415 return 0;
416}
417
418int platform_switch_voice_call_device_post(void *platform,
419 snd_device_t out_snd_device,
420 snd_device_t in_snd_device)
421{
422 struct platform_data *my_data = (struct platform_data *)platform;
423 int acdb_rx_id, acdb_tx_id;
424
425 if (my_data->acdb_send_voice_cal == NULL) {
426 ALOGE("%s: dlsym error for acdb_send_voice_call", __func__);
427 } else {
428 acdb_rx_id = acdb_device_table[out_snd_device];
429 acdb_tx_id = acdb_device_table[in_snd_device];
430
431 if (acdb_rx_id > 0 && acdb_tx_id > 0)
432 my_data->acdb_send_voice_cal(acdb_rx_id, acdb_tx_id);
433 else
434 ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__,
435 acdb_rx_id, acdb_tx_id);
436 }
437
438 return 0;
439}
440
441int platform_start_voice_call(void *platform)
442{
443 return 0;
444}
445
446int platform_stop_voice_call(void *platform)
447{
448 return 0;
449}
450
451int platform_set_voice_volume(void *platform, int volume)
452{
453 struct platform_data *my_data = (struct platform_data *)platform;
454 struct audio_device *adev = my_data->adev;
455 struct mixer_ctl *ctl;
sangwoo53b2cf02013-07-25 19:18:44 -0700456 const char *mixer_ctl_name = "Voice Rx Gain";
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700457 int vol_index = 0;
458 uint32_t set_values[ ] = {0,
459 ALL_SESSION_VSID,
460 DEFAULT_VOLUME_RAMP_DURATION_MS};
Eric Laurentb23d5282013-05-14 15:27:20 -0700461
462 // Voice volume levels are mapped to adsp volume levels as follows.
463 // 100 -> 5, 80 -> 4, 60 -> 3, 40 -> 2, 20 -> 1 0 -> 0
464 // But this values don't changed in kernel. So, below change is need.
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700465 vol_index = (int)percent_to_index(volume, MIN_VOL_INDEX, MAX_VOL_INDEX);
466 set_values[0] = vol_index;
Eric Laurentb23d5282013-05-14 15:27:20 -0700467
468 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
469 if (!ctl) {
470 ALOGE("%s: Could not get ctl for mixer cmd - %s",
471 __func__, mixer_ctl_name);
472 return -EINVAL;
473 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700474 ALOGV("Setting voice volume index: %d", set_values[0]);
475 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
Eric Laurentb23d5282013-05-14 15:27:20 -0700476
477 return 0;
478}
479
480int platform_set_mic_mute(void *platform, bool state)
481{
482 struct platform_data *my_data = (struct platform_data *)platform;
483 struct audio_device *adev = my_data->adev;
484 struct mixer_ctl *ctl;
485 const char *mixer_ctl_name = "Voice Tx Mute";
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700486 uint32_t set_values[ ] = {0,
487 ALL_SESSION_VSID,
488 DEFAULT_VOLUME_RAMP_DURATION_MS};
Eric Laurentb23d5282013-05-14 15:27:20 -0700489
490 if (adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700491 set_values[0] = state;
Eric Laurentb23d5282013-05-14 15:27:20 -0700492 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
493 if (!ctl) {
494 ALOGE("%s: Could not get ctl for mixer cmd - %s",
495 __func__, mixer_ctl_name);
496 return -EINVAL;
497 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700498 ALOGV("Setting voice mute state: %d", state);
499 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
Eric Laurentb23d5282013-05-14 15:27:20 -0700500 }
501
502 return 0;
503}
504
505snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices)
506{
507 struct platform_data *my_data = (struct platform_data *)platform;
508 struct audio_device *adev = my_data->adev;
509 audio_mode_t mode = adev->mode;
510 snd_device_t snd_device = SND_DEVICE_NONE;
511
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700512 audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
513 AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
514 int channel_count = popcount(channel_mask);
515
Eric Laurentb23d5282013-05-14 15:27:20 -0700516 ALOGV("%s: enter: output devices(%#x)", __func__, devices);
517 if (devices == AUDIO_DEVICE_NONE ||
518 devices & AUDIO_DEVICE_BIT_IN) {
519 ALOGV("%s: Invalid output devices (%#x)", __func__, devices);
520 goto exit;
521 }
522
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700523 if(devices & AUDIO_DEVICE_OUT_PROXY) {
524 ALOGD("%s: setting sink capability for Proxy", __func__);
525 audio_extn_set_afe_proxy_channel_mixer(adev);
526 }
527
Eric Laurentb23d5282013-05-14 15:27:20 -0700528 if (mode == AUDIO_MODE_IN_CALL) {
529 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
530 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700531 if (adev->voice.tty_mode == TTY_MODE_FULL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700532 snd_device = SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES;
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700533 } else if (adev->voice.tty_mode == TTY_MODE_VCO) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700534 snd_device = SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES;
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700535 } else if (adev->voice.tty_mode == TTY_MODE_HCO) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700536 snd_device = SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET;
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700537 } else if (audio_extn_get_anc_enabled()) {
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700538 if (audio_extn_should_use_fb_anc())
539 snd_device = SND_DEVICE_OUT_VOICE_ANC_FB_HEADSET;
540 else
541 snd_device = SND_DEVICE_OUT_VOICE_ANC_HEADSET;
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700542 } else {
Eric Laurentb23d5282013-05-14 15:27:20 -0700543 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES;
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700544 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700545 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700546 if (my_data->btsco_sample_rate == SAMPLE_RATE_16KHZ)
547 snd_device = SND_DEVICE_OUT_BT_SCO_WB;
548 else
549 snd_device = SND_DEVICE_OUT_BT_SCO;
Eric Laurentb23d5282013-05-14 15:27:20 -0700550 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
551 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700552 } else if (devices & AUDIO_DEVICE_OUT_FM_TX) {
553 snd_device = SND_DEVICE_OUT_TRANSMISSION_FM;
Eric Laurentb23d5282013-05-14 15:27:20 -0700554 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
555 if (is_operator_tmus())
556 snd_device = SND_DEVICE_OUT_VOICE_HANDSET_TMUS;
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700557 else if (audio_extn_should_use_handset_anc(channel_count))
558 snd_device = SND_DEVICE_OUT_ANC_HANDSET;
Eric Laurentb23d5282013-05-14 15:27:20 -0700559 else
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700560 snd_device = SND_DEVICE_OUT_VOICE_HANDSET;
Eric Laurentb23d5282013-05-14 15:27:20 -0700561 }
562 if (snd_device != SND_DEVICE_NONE) {
563 goto exit;
564 }
565 }
566
567 if (popcount(devices) == 2) {
568 if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
569 AUDIO_DEVICE_OUT_SPEAKER)) {
570 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
571 } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
572 AUDIO_DEVICE_OUT_SPEAKER)) {
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700573 if (audio_extn_get_anc_enabled())
574 snd_device = SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET;
575 else
576 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
Eric Laurentb23d5282013-05-14 15:27:20 -0700577 } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL |
578 AUDIO_DEVICE_OUT_SPEAKER)) {
579 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
580 } else {
581 ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
582 goto exit;
583 }
584 if (snd_device != SND_DEVICE_NONE) {
585 goto exit;
586 }
587 }
588
589 if (popcount(devices) != 1) {
590 ALOGE("%s: Invalid output devices(%#x)", __func__, devices);
591 goto exit;
592 }
593
594 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
595 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700596 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADSET
597 && audio_extn_get_anc_enabled()) {
598 if (audio_extn_should_use_fb_anc())
599 snd_device = SND_DEVICE_OUT_ANC_FB_HEADSET;
600 else
601 snd_device = SND_DEVICE_OUT_ANC_HEADSET;
602 }
603 else
604 snd_device = SND_DEVICE_OUT_HEADPHONES;
Eric Laurentb23d5282013-05-14 15:27:20 -0700605 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
606 if (adev->speaker_lr_swap)
607 snd_device = SND_DEVICE_OUT_SPEAKER_REVERSE;
608 else
609 snd_device = SND_DEVICE_OUT_SPEAKER;
610 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700611 if (my_data->btsco_sample_rate == SAMPLE_RATE_16KHZ)
612 snd_device = SND_DEVICE_OUT_BT_SCO_WB;
613 else
614 snd_device = SND_DEVICE_OUT_BT_SCO;
Eric Laurentb23d5282013-05-14 15:27:20 -0700615 } else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
616 snd_device = SND_DEVICE_OUT_HDMI ;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700617 } else if (devices & AUDIO_DEVICE_OUT_FM_TX) {
618 snd_device = SND_DEVICE_OUT_TRANSMISSION_FM;
Eric Laurentb23d5282013-05-14 15:27:20 -0700619 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
620 snd_device = SND_DEVICE_OUT_HANDSET;
621 } else {
622 ALOGE("%s: Unknown device(s) %#x", __func__, devices);
623 }
624exit:
625 ALOGV("%s: exit: snd_device(%s)", __func__, device_table[snd_device]);
626 return snd_device;
627}
628
629snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device)
630{
631 struct platform_data *my_data = (struct platform_data *)platform;
632 struct audio_device *adev = my_data->adev;
633 audio_source_t source = (adev->active_input == NULL) ?
634 AUDIO_SOURCE_DEFAULT : adev->active_input->source;
635
636 audio_mode_t mode = adev->mode;
637 audio_devices_t in_device = ((adev->active_input == NULL) ?
638 AUDIO_DEVICE_NONE : adev->active_input->device)
639 & ~AUDIO_DEVICE_BIT_IN;
640 audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
641 AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
642 snd_device_t snd_device = SND_DEVICE_NONE;
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700643 int channel_count = popcount(channel_mask);
Eric Laurentb23d5282013-05-14 15:27:20 -0700644
645 ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
646 __func__, out_device, in_device);
647 if (mode == AUDIO_MODE_IN_CALL) {
648 if (out_device == AUDIO_DEVICE_NONE) {
649 ALOGE("%s: No output device set for voice call", __func__);
650 goto exit;
651 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700652 if (adev->voice.tty_mode != TTY_MODE_OFF) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700653 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
654 out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700655 switch (adev->voice.tty_mode) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700656 case TTY_MODE_FULL:
657 snd_device = SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC;
658 break;
659 case TTY_MODE_VCO:
660 snd_device = SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC;
661 break;
662 case TTY_MODE_HCO:
663 snd_device = SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC;
664 break;
665 default:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700666 ALOGE("%s: Invalid TTY mode (%#x)",
667 __func__, adev->voice.tty_mode);
Eric Laurentb23d5282013-05-14 15:27:20 -0700668 }
669 goto exit;
670 }
671 }
672 if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
673 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700674 if (out_device & AUDIO_DEVICE_OUT_EARPIECE &&
675 audio_extn_should_use_handset_anc(channel_count)) {
676 snd_device = SND_DEVICE_IN_AANC_HANDSET_MIC;
677 } else if (my_data->fluence_type == FLUENCE_NONE ||
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700678 my_data->fluence_in_voice_call == false) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700679 snd_device = SND_DEVICE_IN_HANDSET_MIC;
680 } else {
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700681 if (is_operator_tmus())
682 snd_device = SND_DEVICE_IN_VOICE_DMIC_TMUS;
Eric Laurentb23d5282013-05-14 15:27:20 -0700683 else
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700684 snd_device = SND_DEVICE_IN_VOICE_DMIC;
685 adev->acdb_settings |= DMIC_FLAG;
Eric Laurentb23d5282013-05-14 15:27:20 -0700686 }
687 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
688 snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
689 } else if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700690 if (my_data->btsco_sample_rate == SAMPLE_RATE_16KHZ)
691 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
692 else
693 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
Eric Laurentb23d5282013-05-14 15:27:20 -0700694 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700695 if (my_data->fluence_type != FLUENCE_NONE &&
696 my_data->fluence_in_voice_call &&
697 my_data->fluence_in_spkr_mode) {
698 if(my_data->fluence_type == FLUENCE_DUAL_MIC) {
699 adev->acdb_settings |= DMIC_FLAG;
700 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC;
701 } else {
702 adev->acdb_settings |= QMIC_FLAG;
703 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_QMIC;
704 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700705 } else {
706 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
707 }
708 }
709 } else if (source == AUDIO_SOURCE_CAMCORDER) {
710 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
711 in_device & AUDIO_DEVICE_IN_BACK_MIC) {
712 snd_device = SND_DEVICE_IN_CAMCORDER_MIC;
713 }
714 } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) {
715 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700716 if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
717 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC;
718 else if (my_data->fluence_in_voice_rec)
719 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE;
Eric Laurentb23d5282013-05-14 15:27:20 -0700720
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700721 if (snd_device == SND_DEVICE_NONE)
Eric Laurentb23d5282013-05-14 15:27:20 -0700722 snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700723 else
724 adev->acdb_settings |= DMIC_FLAG;
Eric Laurentb23d5282013-05-14 15:27:20 -0700725 }
726 } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
727 if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
728 in_device = AUDIO_DEVICE_IN_BACK_MIC;
729 if (adev->active_input) {
730 if (adev->active_input->enable_aec) {
731 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
732 snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
733 } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
734 snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
735 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
736 snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
737 }
738 set_echo_reference(adev->mixer, "SLIM_RX");
739 } else
740 set_echo_reference(adev->mixer, "NONE");
741 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700742 } else if (source == AUDIO_SOURCE_FM_RX) {
743 if (in_device & AUDIO_DEVICE_IN_FM_RX) {
744 snd_device = SND_DEVICE_IN_CAPTURE_FM;
745 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700746 } else if (source == AUDIO_SOURCE_DEFAULT) {
747 goto exit;
748 }
749
750
751 if (snd_device != SND_DEVICE_NONE) {
752 goto exit;
753 }
754
755 if (in_device != AUDIO_DEVICE_NONE &&
756 !(in_device & AUDIO_DEVICE_IN_VOICE_CALL) &&
757 !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) {
758 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
759 snd_device = SND_DEVICE_IN_HANDSET_MIC;
760 } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
761 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
762 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
763 snd_device = SND_DEVICE_IN_HEADSET_MIC;
764 } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700765 if (my_data->btsco_sample_rate == SAMPLE_RATE_16KHZ)
766 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
767 else
768 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
Eric Laurentb23d5282013-05-14 15:27:20 -0700769 } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) {
770 snd_device = SND_DEVICE_IN_HDMI_MIC;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700771 } else if (in_device & AUDIO_DEVICE_IN_FM_RX) {
772 snd_device = SND_DEVICE_IN_CAPTURE_FM;
Eric Laurentb23d5282013-05-14 15:27:20 -0700773 } else {
774 ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
775 ALOGW("%s: Using default handset-mic", __func__);
776 snd_device = SND_DEVICE_IN_HANDSET_MIC;
777 }
778 } else {
779 if (out_device & AUDIO_DEVICE_OUT_EARPIECE) {
780 snd_device = SND_DEVICE_IN_HANDSET_MIC;
781 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
782 snd_device = SND_DEVICE_IN_HEADSET_MIC;
783 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
784 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
785 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
786 snd_device = SND_DEVICE_IN_HANDSET_MIC;
787 } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700788 if (my_data->btsco_sample_rate == SAMPLE_RATE_16KHZ)
789 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
790 else
791 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
Eric Laurentb23d5282013-05-14 15:27:20 -0700792 } else if (out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
793 snd_device = SND_DEVICE_IN_HDMI_MIC;
794 } else {
795 ALOGE("%s: Unknown output device(s) %#x", __func__, out_device);
796 ALOGW("%s: Using default handset-mic", __func__);
797 snd_device = SND_DEVICE_IN_HANDSET_MIC;
798 }
799 }
800exit:
801 ALOGV("%s: exit: in_snd_device(%s)", __func__, device_table[snd_device]);
802 return snd_device;
803}
804
805int platform_set_hdmi_channels(void *platform, int channel_count)
806{
807 struct platform_data *my_data = (struct platform_data *)platform;
808 struct audio_device *adev = my_data->adev;
809 struct mixer_ctl *ctl;
810 const char *channel_cnt_str = NULL;
811 const char *mixer_ctl_name = "HDMI_RX Channels";
812 switch (channel_count) {
813 case 8:
814 channel_cnt_str = "Eight"; break;
815 case 7:
816 channel_cnt_str = "Seven"; break;
817 case 6:
818 channel_cnt_str = "Six"; break;
819 case 5:
820 channel_cnt_str = "Five"; break;
821 case 4:
822 channel_cnt_str = "Four"; break;
823 case 3:
824 channel_cnt_str = "Three"; break;
825 default:
826 channel_cnt_str = "Two"; break;
827 }
828 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
829 if (!ctl) {
830 ALOGE("%s: Could not get ctl for mixer cmd - %s",
831 __func__, mixer_ctl_name);
832 return -EINVAL;
833 }
834 ALOGV("HDMI channel count: %s", channel_cnt_str);
835 mixer_ctl_set_enum_by_string(ctl, channel_cnt_str);
836 return 0;
837}
838
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700839int platform_edid_get_max_channels(void *platform)
Eric Laurentb23d5282013-05-14 15:27:20 -0700840{
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700841 struct platform_data *my_data = (struct platform_data *)platform;
842 struct audio_device *adev = my_data->adev;
Eric Laurentb23d5282013-05-14 15:27:20 -0700843 char block[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE];
844 char *sad = block;
845 int num_audio_blocks;
846 int channel_count;
847 int max_channels = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700848 int i, ret, count;
Eric Laurentb23d5282013-05-14 15:27:20 -0700849
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700850 struct mixer_ctl *ctl;
851
852 ctl = mixer_get_ctl_by_name(adev->mixer, AUDIO_DATA_BLOCK_MIXER_CTL);
853 if (!ctl) {
854 ALOGE("%s: Could not get ctl for mixer cmd - %s",
855 __func__, AUDIO_DATA_BLOCK_MIXER_CTL);
Eric Laurentb23d5282013-05-14 15:27:20 -0700856 return 0;
857 }
858
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700859 mixer_ctl_update(ctl);
860
861 count = mixer_ctl_get_num_values(ctl);
Eric Laurentb23d5282013-05-14 15:27:20 -0700862
863 /* Read SAD blocks, clamping the maximum size for safety */
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700864 if (count > (int)sizeof(block))
865 count = (int)sizeof(block);
Eric Laurentb23d5282013-05-14 15:27:20 -0700866
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700867 ret = mixer_ctl_get_array(ctl, block, count);
868 if (ret != 0) {
869 ALOGE("%s: mixer_ctl_get_array() failed to get EDID info", __func__);
870 return 0;
871 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700872
873 /* Calculate the number of SAD blocks */
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700874 num_audio_blocks = count / SAD_BLOCK_SIZE;
Eric Laurentb23d5282013-05-14 15:27:20 -0700875
876 for (i = 0; i < num_audio_blocks; i++) {
877 /* Only consider LPCM blocks */
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700878 if ((sad[0] >> 3) != EDID_FORMAT_LPCM) {
879 sad += 3;
Eric Laurentb23d5282013-05-14 15:27:20 -0700880 continue;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700881 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700882
883 channel_count = (sad[0] & 0x7) + 1;
884 if (channel_count > max_channels)
885 max_channels = channel_count;
886
887 /* Advance to next block */
888 sad += 3;
889 }
890
891 return max_channels;
892}
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700893
894static int platform_set_slowtalk(struct platform_data *my_data, bool state)
895{
896 int ret = 0;
897 struct audio_device *adev = my_data->adev;
898 struct mixer_ctl *ctl;
899 const char *mixer_ctl_name = "Slowtalk Enable";
900 uint32_t set_values[ ] = {0,
901 ALL_SESSION_VSID};
902
903 set_values[0] = state;
904 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
905 if (!ctl) {
906 ALOGE("%s: Could not get ctl for mixer cmd - %s",
907 __func__, mixer_ctl_name);
908 ret = -EINVAL;
909 } else {
910 ALOGV("Setting slowtalk state: %d", state);
911 ret = mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
912 my_data->slowtalk = state;
913 }
914
915 return ret;
916}
917
918int platform_set_parameters(void *platform, struct str_parms *parms)
919{
920 struct platform_data *my_data = (struct platform_data *)platform;
921 char *str;
922 char value[32];
923 int val;
924 int ret = 0;
925
926 ALOGV("%s: enter: %s", __func__, str_parms_to_str(parms));
927
928 ret = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_BTSCO, &val);
929 if (ret >= 0) {
930 str_parms_del(parms, AUDIO_PARAMETER_KEY_BTSCO);
931 pthread_mutex_lock(&my_data->adev->lock);
932 my_data->btsco_sample_rate = val;
933 pthread_mutex_unlock(&my_data->adev->lock);
934 }
935
936 ret = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_SLOWTALK, &val);
937 if (ret >= 0) {
938 str_parms_del(parms, AUDIO_PARAMETER_KEY_SLOWTALK);
939 pthread_mutex_lock(&my_data->adev->lock);
940 ret = platform_set_slowtalk(my_data, val);
941 if (ret)
942 ALOGE("%s: Failed to set slow talk err: %d", __func__, ret);
943 pthread_mutex_unlock(&my_data->adev->lock);
944 }
945
946 ALOGV("%s: exit with code(%d)", __func__, ret);
947 return ret;
948}
949
950void platform_get_parameters(void *platform,
951 struct str_parms *query,
952 struct str_parms *reply)
953{
954 struct platform_data *my_data = (struct platform_data *)platform;
955 char *str = NULL;
956 char value[256] = {0};
957 int ret;
958 int fluence_type;
959
960 ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_FLUENCE_TYPE,
961 value, sizeof(value));
962 if (ret >= 0) {
963 pthread_mutex_lock(&my_data->adev->lock);
964 if (my_data->fluence_type == FLUENCE_QUAD_MIC) {
965 strlcpy(value, "fluencepro", sizeof(value));
966 } else if (my_data->fluence_type == FLUENCE_DUAL_MIC) {
967 strlcpy(value, "fluence", sizeof(value));
968 } else {
969 strlcpy(value, "none", sizeof(value));
970 }
971 pthread_mutex_unlock(&my_data->adev->lock);
972
973 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_FLUENCE_TYPE, value);
974 }
975
976 ALOGV("%s: exit: returns - %s", __func__, str_parms_to_str(reply));
977}
978