blob: cd7150cdd490040825bb29b2c805bf0e9b53ed36 [file] [log] [blame]
Eric Laurentb23d5282013-05-14 15:27:20 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "msm8974_platform"
18/*#define LOG_NDEBUG 0*/
19#define LOG_NDDEBUG 0
20
21#include <stdlib.h>
22#include <dlfcn.h>
23#include <cutils/log.h>
24#include <cutils/properties.h>
25#include <audio_hw.h>
26#include <platform_api.h>
27#include "platform.h"
28
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -070029#define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
Eric Laurentb23d5282013-05-14 15:27:20 -070030#define LIB_ACDB_LOADER "libacdbloader.so"
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -070031#define AUDIO_DATA_BLOCK_MIXER_CTL "HDMI EDID"
Eric Laurentb23d5282013-05-14 15:27:20 -070032
33#define DUALMIC_CONFIG_NONE 0 /* Target does not contain 2 mics */
34#define DUALMIC_CONFIG_ENDFIRE 1
35#define DUALMIC_CONFIG_BROADSIDE 2
36
37/*
Eric Laurentb23d5282013-05-14 15:27:20 -070038 * This file will have a maximum of 38 bytes:
39 *
40 * 4 bytes: number of audio blocks
41 * 4 bytes: total length of Short Audio Descriptor (SAD) blocks
42 * Maximum 10 * 3 bytes: SAD blocks
43 */
44#define MAX_SAD_BLOCKS 10
45#define SAD_BLOCK_SIZE 3
46
47/* EDID format ID for LPCM audio */
48#define EDID_FORMAT_LPCM 1
49
sangwoo1b9f4b32013-06-21 18:22:55 -070050/* Retry for delay in FW loading*/
51#define RETRY_NUMBER 10
52#define RETRY_US 500000
53
sangwoo53b2cf02013-07-25 19:18:44 -070054#define MAX_VOL_INDEX 5
55#define MIN_VOL_INDEX 0
56#define percent_to_index(val, min, max) \
57 ((val) * ((max) - (min)) * 0.01 + (min) + .5)
58
Eric Laurentb23d5282013-05-14 15:27:20 -070059struct audio_block_header
60{
61 int reserved;
62 int length;
63};
64
65typedef void (*acdb_deallocate_t)();
66typedef int (*acdb_init_t)();
67typedef void (*acdb_send_audio_cal_t)(int, int);
68typedef void (*acdb_send_voice_cal_t)(int, int);
69
70/* Audio calibration related functions */
71struct platform_data {
72 struct audio_device *adev;
73 bool fluence_in_spkr_mode;
74 bool fluence_in_voice_call;
75 bool fluence_in_voice_rec;
76 int dualmic_config;
77
78 void *acdb_handle;
79 acdb_init_t acdb_init;
80 acdb_deallocate_t acdb_deallocate;
81 acdb_send_audio_cal_t acdb_send_audio_cal;
82 acdb_send_voice_cal_t acdb_send_voice_cal;
83};
84
85static const int pcm_device_table[AUDIO_USECASE_MAX][2] = {
86 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
87 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
88 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070089 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
Eric Laurentb23d5282013-05-14 15:27:20 -070090 [USECASE_AUDIO_RECORD] = {0, 0},
91 [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
92 [USECASE_VOICE_CALL] = {2, 2},
93};
94
95/* Array to store sound devices */
96static const char * const device_table[SND_DEVICE_MAX] = {
97 [SND_DEVICE_NONE] = "none",
98 /* Playback sound devices */
99 [SND_DEVICE_OUT_HANDSET] = "handset",
100 [SND_DEVICE_OUT_SPEAKER] = "speaker",
101 [SND_DEVICE_OUT_SPEAKER_REVERSE] = "speaker-reverse",
102 [SND_DEVICE_OUT_HEADPHONES] = "headphones",
103 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones",
104 [SND_DEVICE_OUT_VOICE_HANDSET] = "voice-handset",
105 [SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker",
106 [SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones",
107 [SND_DEVICE_OUT_HDMI] = "hdmi",
108 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
109 [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
110 [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = "voice-handset-tmus",
111 [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = "voice-tty-full-headphones",
112 [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = "voice-tty-vco-headphones",
113 [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = "voice-tty-hco-handset",
114
115 /* Capture sound devices */
116 [SND_DEVICE_IN_HANDSET_MIC] = "handset-mic",
117 [SND_DEVICE_IN_SPEAKER_MIC] = "speaker-mic",
118 [SND_DEVICE_IN_HEADSET_MIC] = "headset-mic",
119 [SND_DEVICE_IN_HANDSET_MIC_AEC] = "handset-mic",
120 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = "voice-speaker-mic",
121 [SND_DEVICE_IN_HEADSET_MIC_AEC] = "headset-mic",
122 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "voice-speaker-mic",
123 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "voice-headset-mic",
124 [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic",
125 [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic",
126 [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic",
127 [SND_DEVICE_IN_VOICE_DMIC_EF] = "voice-dmic-ef",
128 [SND_DEVICE_IN_VOICE_DMIC_BS] = "voice-dmic-bs",
129 [SND_DEVICE_IN_VOICE_DMIC_EF_TMUS] = "voice-dmic-ef-tmus",
130 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF] = "voice-speaker-dmic-ef",
131 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS] = "voice-speaker-dmic-bs",
132 [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = "voice-tty-full-headset-mic",
133 [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = "voice-tty-vco-handset-mic",
134 [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = "voice-tty-hco-headset-mic",
135 [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic",
136 [SND_DEVICE_IN_VOICE_REC_DMIC_EF] = "voice-rec-dmic-ef",
137 [SND_DEVICE_IN_VOICE_REC_DMIC_BS] = "voice-rec-dmic-bs",
138 [SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE] = "voice-rec-dmic-ef-fluence",
139 [SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE] = "voice-rec-dmic-bs-fluence",
140};
141
142/* ACDB IDs (audio DSP path configuration IDs) for each sound device */
143static const int acdb_device_table[SND_DEVICE_MAX] = {
144 [SND_DEVICE_NONE] = -1,
145 [SND_DEVICE_OUT_HANDSET] = 7,
146 [SND_DEVICE_OUT_SPEAKER] = 15,
147 [SND_DEVICE_OUT_SPEAKER_REVERSE] = 15,
148 [SND_DEVICE_OUT_HEADPHONES] = 10,
149 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = 10,
150 [SND_DEVICE_OUT_VOICE_HANDSET] = 7,
151 [SND_DEVICE_OUT_VOICE_SPEAKER] = 15,
152 [SND_DEVICE_OUT_VOICE_HEADPHONES] = 10,
153 [SND_DEVICE_OUT_HDMI] = 18,
154 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 15,
155 [SND_DEVICE_OUT_BT_SCO] = 22,
sangwooc69476f2013-07-26 16:57:26 -0700156 [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = 88,
Eric Laurentb23d5282013-05-14 15:27:20 -0700157 [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = 17,
158 [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = 17,
159 [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = 37,
160
161 [SND_DEVICE_IN_HANDSET_MIC] = 4,
162 [SND_DEVICE_IN_SPEAKER_MIC] = 4, /* ToDo: Check if this needs to changed to 11 */
163 [SND_DEVICE_IN_HEADSET_MIC] = 8,
164 [SND_DEVICE_IN_HANDSET_MIC_AEC] = 40,
165 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = 42,
166 [SND_DEVICE_IN_HEADSET_MIC_AEC] = 47,
167 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = 11,
168 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = 8,
169 [SND_DEVICE_IN_HDMI_MIC] = 4,
170 [SND_DEVICE_IN_BT_SCO_MIC] = 21,
171 [SND_DEVICE_IN_CAMCORDER_MIC] = 61,
172 [SND_DEVICE_IN_VOICE_DMIC_EF] = 41,
173 [SND_DEVICE_IN_VOICE_DMIC_BS] = 5,
sangwooc69476f2013-07-26 16:57:26 -0700174 [SND_DEVICE_IN_VOICE_DMIC_EF_TMUS] = 89,
Eric Laurentb23d5282013-05-14 15:27:20 -0700175 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF] = 43,
176 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS] = 12,
177 [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = 16,
178 [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = 36,
179 [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = 16,
180 [SND_DEVICE_IN_VOICE_REC_MIC] = 62,
181 /* TODO: Update with proper acdb ids */
182 [SND_DEVICE_IN_VOICE_REC_DMIC_EF] = 62,
183 [SND_DEVICE_IN_VOICE_REC_DMIC_BS] = 62,
184 [SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE] = 6,
185 [SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE] = 5,
186};
187
188static pthread_once_t check_op_once_ctl = PTHREAD_ONCE_INIT;
189static bool is_tmus = false;
190
191static void check_operator()
192{
193 char value[PROPERTY_VALUE_MAX];
194 int mccmnc;
195 property_get("gsm.sim.operator.numeric",value,"0");
196 mccmnc = atoi(value);
197 ALOGD("%s: tmus mccmnc %d", __func__, mccmnc);
198 switch(mccmnc) {
199 /* TMUS MCC(310), MNC(490, 260, 026) */
200 case 310490:
201 case 310260:
202 case 310026:
sangwon.jeonb891db52013-09-14 17:39:15 +0900203 /* Add new TMUS MNC(800, 660, 580, 310, 270, 250, 240, 230, 220, 210, 200, 160) */
204 case 310800:
205 case 310660:
206 case 310580:
207 case 310310:
208 case 310270:
209 case 310250:
210 case 310240:
211 case 310230:
212 case 310220:
213 case 310210:
214 case 310200:
215 case 310160:
Eric Laurentb23d5282013-05-14 15:27:20 -0700216 is_tmus = true;
217 break;
218 }
219}
220
221bool is_operator_tmus()
222{
223 pthread_once(&check_op_once_ctl, check_operator);
224 return is_tmus;
225}
226
sangwoo53b2cf02013-07-25 19:18:44 -0700227static int set_volume_values(int type, int volume, int* values)
228{
229 values[0] = volume;
230 values[1] = ALL_SESSION_VSID;
231
232 switch(type) {
233 case VOLUME_SET:
234 values[2] = DEFAULT_VOLUME_RAMP_DURATION_MS;
235 break;
236 case MUTE_SET:
237 values[2] = DEFAULT_MUTE_RAMP_DURATION;
238 break;
239 default:
240 return -EINVAL;
241 }
242 return 0;
243}
244
Eric Laurentb23d5282013-05-14 15:27:20 -0700245static 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;
289 my_data->dualmic_config = DUALMIC_CONFIG_NONE;
290 my_data->fluence_in_spkr_mode = false;
291 my_data->fluence_in_voice_call = false;
292 my_data->fluence_in_voice_rec = false;
293
294 property_get("persist.audio.dualmic.config",value,"");
295 if (!strcmp("broadside", value)) {
296 my_data->dualmic_config = DUALMIC_CONFIG_BROADSIDE;
297 adev->acdb_settings |= DMIC_FLAG;
298 } else if (!strcmp("endfire", value)) {
299 my_data->dualmic_config = DUALMIC_CONFIG_ENDFIRE;
300 adev->acdb_settings |= DMIC_FLAG;
301 }
302
303 if (my_data->dualmic_config != DUALMIC_CONFIG_NONE) {
304 property_get("persist.audio.fluence.voicecall",value,"");
305 if (!strcmp("true", value)) {
306 my_data->fluence_in_voice_call = true;
307 }
308
309 property_get("persist.audio.fluence.voicerec",value,"");
310 if (!strcmp("true", value)) {
311 my_data->fluence_in_voice_rec = true;
312 }
313
314 property_get("persist.audio.fluence.speaker",value,"");
315 if (!strcmp("true", value)) {
316 my_data->fluence_in_spkr_mode = true;
317 }
318 }
319
320 my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
321 if (my_data->acdb_handle == NULL) {
322 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_ACDB_LOADER);
323 } else {
324 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_ACDB_LOADER);
325 my_data->acdb_deallocate = (acdb_deallocate_t)dlsym(my_data->acdb_handle,
326 "acdb_loader_deallocate_ACDB");
327 my_data->acdb_send_audio_cal = (acdb_send_audio_cal_t)dlsym(my_data->acdb_handle,
328 "acdb_loader_send_audio_cal");
329 if (!my_data->acdb_send_audio_cal)
330 ALOGW("%s: Could not find the symbol acdb_send_audio_cal from %s",
331 __func__, LIB_ACDB_LOADER);
332 my_data->acdb_send_voice_cal = (acdb_send_voice_cal_t)dlsym(my_data->acdb_handle,
333 "acdb_loader_send_voice_cal");
334 my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
335 "acdb_loader_init_ACDB");
336 if (my_data->acdb_init == NULL)
337 ALOGE("%s: dlsym error %s for acdb_loader_init_ACDB", __func__, dlerror());
338 else
339 my_data->acdb_init();
340 }
341
342 return my_data;
343}
344
345void platform_deinit(void *platform)
346{
347 free(platform);
348}
349
350const char *platform_get_snd_device_name(snd_device_t snd_device)
351{
352 if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX)
353 return device_table[snd_device];
354 else
355 return "";
356}
357
358void platform_add_backend_name(char *mixer_path, snd_device_t snd_device)
359{
360 if (snd_device == SND_DEVICE_IN_BT_SCO_MIC)
361 strcat(mixer_path, " bt-sco");
362 else if(snd_device == SND_DEVICE_OUT_BT_SCO)
363 strcat(mixer_path, " bt-sco");
364 else if (snd_device == SND_DEVICE_OUT_HDMI)
365 strcat(mixer_path, " hdmi");
366 else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HDMI)
367 strcat(mixer_path, " speaker-and-hdmi");
368}
369
370int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type)
371{
372 int device_id;
373 if (device_type == PCM_PLAYBACK)
374 device_id = pcm_device_table[usecase][0];
375 else
376 device_id = pcm_device_table[usecase][1];
377 return device_id;
378}
379
380int platform_send_audio_calibration(void *platform, snd_device_t snd_device)
381{
382 struct platform_data *my_data = (struct platform_data *)platform;
383 int acdb_dev_id, acdb_dev_type;
384
385 acdb_dev_id = acdb_device_table[snd_device];
386 if (acdb_dev_id < 0) {
387 ALOGE("%s: Could not find acdb id for device(%d)",
388 __func__, snd_device);
389 return -EINVAL;
390 }
391 if (my_data->acdb_send_audio_cal) {
Eric Laurent994a6932013-07-17 11:51:42 -0700392 ("%s: sending audio calibration for snd_device(%d) acdb_id(%d)",
Eric Laurentb23d5282013-05-14 15:27:20 -0700393 __func__, snd_device, acdb_dev_id);
394 if (snd_device >= SND_DEVICE_OUT_BEGIN &&
395 snd_device < SND_DEVICE_OUT_END)
396 acdb_dev_type = ACDB_DEV_TYPE_OUT;
397 else
398 acdb_dev_type = ACDB_DEV_TYPE_IN;
399 my_data->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type);
400 }
401 return 0;
402}
403
404int platform_switch_voice_call_device_pre(void *platform)
405{
406 return 0;
407}
408
409int platform_switch_voice_call_device_post(void *platform,
410 snd_device_t out_snd_device,
411 snd_device_t in_snd_device)
412{
413 struct platform_data *my_data = (struct platform_data *)platform;
414 int acdb_rx_id, acdb_tx_id;
415
416 if (my_data->acdb_send_voice_cal == NULL) {
417 ALOGE("%s: dlsym error for acdb_send_voice_call", __func__);
418 } else {
419 acdb_rx_id = acdb_device_table[out_snd_device];
420 acdb_tx_id = acdb_device_table[in_snd_device];
421
422 if (acdb_rx_id > 0 && acdb_tx_id > 0)
423 my_data->acdb_send_voice_cal(acdb_rx_id, acdb_tx_id);
424 else
425 ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__,
426 acdb_rx_id, acdb_tx_id);
427 }
428
429 return 0;
430}
431
432int platform_start_voice_call(void *platform)
433{
434 return 0;
435}
436
437int platform_stop_voice_call(void *platform)
438{
439 return 0;
440}
441
442int platform_set_voice_volume(void *platform, int volume)
443{
444 struct platform_data *my_data = (struct platform_data *)platform;
445 struct audio_device *adev = my_data->adev;
446 struct mixer_ctl *ctl;
sangwoo53b2cf02013-07-25 19:18:44 -0700447 const char *mixer_ctl_name = "Voice Rx Gain";
448 int values[VOLUME_CTL_PARAM_NUM];
449 int ret = 0;
Eric Laurentb23d5282013-05-14 15:27:20 -0700450
451 // Voice volume levels are mapped to adsp volume levels as follows.
452 // 100 -> 5, 80 -> 4, 60 -> 3, 40 -> 2, 20 -> 1 0 -> 0
453 // But this values don't changed in kernel. So, below change is need.
sangwoo53b2cf02013-07-25 19:18:44 -0700454 volume = (int)percent_to_index(volume, MIN_VOL_INDEX, MAX_VOL_INDEX);
Eric Laurentb23d5282013-05-14 15:27:20 -0700455
456 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
457 if (!ctl) {
458 ALOGE("%s: Could not get ctl for mixer cmd - %s",
459 __func__, mixer_ctl_name);
460 return -EINVAL;
461 }
sangwoo53b2cf02013-07-25 19:18:44 -0700462 ret = set_volume_values(VOLUME_SET, volume, values);
463 if (ret < 0) {
464 ALOGV("%s: failed setting volume by incorrect type", __func__);
465 return -EINVAL;
466 }
467 ret = mixer_ctl_set_array(ctl, values, sizeof(values)/sizeof(int));
468 if (ret < 0) {
469 ALOGV("%s: failed set mixer ctl by %d", __func__, ret);
470 return -EINVAL;
471 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700472
473 return 0;
474}
475
476int platform_set_mic_mute(void *platform, bool state)
477{
478 struct platform_data *my_data = (struct platform_data *)platform;
479 struct audio_device *adev = my_data->adev;
480 struct mixer_ctl *ctl;
481 const char *mixer_ctl_name = "Voice Tx Mute";
sangwoo53b2cf02013-07-25 19:18:44 -0700482 int values[VOLUME_CTL_PARAM_NUM];
483 int ret = 0;
Eric Laurentb23d5282013-05-14 15:27:20 -0700484
485 if (adev->mode == AUDIO_MODE_IN_CALL) {
486 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
487 if (!ctl) {
488 ALOGE("%s: Could not get ctl for mixer cmd - %s",
489 __func__, mixer_ctl_name);
490 return -EINVAL;
491 }
492 ALOGV("Setting mic mute: %d", state);
sangwoo53b2cf02013-07-25 19:18:44 -0700493 ret = set_volume_values(MUTE_SET, state, values);
494 if (ret < 0) {
495 ALOGV("%s: failed setting mute by incorrect type", __func__);
496 return -EINVAL;
497 }
498 ret = mixer_ctl_set_array(ctl, values, sizeof(values)/sizeof(int));
499 if (ret < 0) {
500 ALOGV("%s: failed set mixer ctl by %d", __func__, ret);
501 return -EINVAL;
502 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700503 }
504
505 return 0;
506}
507
508snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices)
509{
510 struct platform_data *my_data = (struct platform_data *)platform;
511 struct audio_device *adev = my_data->adev;
512 audio_mode_t mode = adev->mode;
513 snd_device_t snd_device = SND_DEVICE_NONE;
514
515 ALOGV("%s: enter: output devices(%#x)", __func__, devices);
516 if (devices == AUDIO_DEVICE_NONE ||
517 devices & AUDIO_DEVICE_BIT_IN) {
518 ALOGV("%s: Invalid output devices (%#x)", __func__, devices);
519 goto exit;
520 }
521
522 if (mode == AUDIO_MODE_IN_CALL) {
523 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
524 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
525 if (adev->tty_mode == TTY_MODE_FULL)
526 snd_device = SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES;
527 else if (adev->tty_mode == TTY_MODE_VCO)
528 snd_device = SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES;
529 else if (adev->tty_mode == TTY_MODE_HCO)
530 snd_device = SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET;
531 else
532 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES;
533 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
534 snd_device = SND_DEVICE_OUT_BT_SCO;
535 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
536 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
537 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
538 if (is_operator_tmus())
539 snd_device = SND_DEVICE_OUT_VOICE_HANDSET_TMUS;
540 else
541 snd_device = SND_DEVICE_OUT_HANDSET;
542 }
543 if (snd_device != SND_DEVICE_NONE) {
544 goto exit;
545 }
546 }
547
548 if (popcount(devices) == 2) {
549 if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
550 AUDIO_DEVICE_OUT_SPEAKER)) {
551 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
552 } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
553 AUDIO_DEVICE_OUT_SPEAKER)) {
554 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
555 } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL |
556 AUDIO_DEVICE_OUT_SPEAKER)) {
557 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
558 } else {
559 ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
560 goto exit;
561 }
562 if (snd_device != SND_DEVICE_NONE) {
563 goto exit;
564 }
565 }
566
567 if (popcount(devices) != 1) {
568 ALOGE("%s: Invalid output devices(%#x)", __func__, devices);
569 goto exit;
570 }
571
572 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
573 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
574 snd_device = SND_DEVICE_OUT_HEADPHONES;
575 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
576 if (adev->speaker_lr_swap)
577 snd_device = SND_DEVICE_OUT_SPEAKER_REVERSE;
578 else
579 snd_device = SND_DEVICE_OUT_SPEAKER;
580 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
581 snd_device = SND_DEVICE_OUT_BT_SCO;
582 } else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
583 snd_device = SND_DEVICE_OUT_HDMI ;
584 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
585 snd_device = SND_DEVICE_OUT_HANDSET;
586 } else {
587 ALOGE("%s: Unknown device(s) %#x", __func__, devices);
588 }
589exit:
590 ALOGV("%s: exit: snd_device(%s)", __func__, device_table[snd_device]);
591 return snd_device;
592}
593
594snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device)
595{
596 struct platform_data *my_data = (struct platform_data *)platform;
597 struct audio_device *adev = my_data->adev;
598 audio_source_t source = (adev->active_input == NULL) ?
599 AUDIO_SOURCE_DEFAULT : adev->active_input->source;
600
601 audio_mode_t mode = adev->mode;
602 audio_devices_t in_device = ((adev->active_input == NULL) ?
603 AUDIO_DEVICE_NONE : adev->active_input->device)
604 & ~AUDIO_DEVICE_BIT_IN;
605 audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
606 AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
607 snd_device_t snd_device = SND_DEVICE_NONE;
608
609 ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
610 __func__, out_device, in_device);
611 if (mode == AUDIO_MODE_IN_CALL) {
612 if (out_device == AUDIO_DEVICE_NONE) {
613 ALOGE("%s: No output device set for voice call", __func__);
614 goto exit;
615 }
616 if (adev->tty_mode != TTY_MODE_OFF) {
617 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
618 out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
619 switch (adev->tty_mode) {
620 case TTY_MODE_FULL:
621 snd_device = SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC;
622 break;
623 case TTY_MODE_VCO:
624 snd_device = SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC;
625 break;
626 case TTY_MODE_HCO:
627 snd_device = SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC;
628 break;
629 default:
630 ALOGE("%s: Invalid TTY mode (%#x)", __func__, adev->tty_mode);
631 }
632 goto exit;
633 }
634 }
635 if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
636 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
637 if (my_data->fluence_in_voice_call == false) {
638 snd_device = SND_DEVICE_IN_HANDSET_MIC;
639 } else {
640 if (my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
641 if (is_operator_tmus())
642 snd_device = SND_DEVICE_IN_VOICE_DMIC_EF_TMUS;
643 else
644 snd_device = SND_DEVICE_IN_VOICE_DMIC_EF;
645 } else if(my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE)
646 snd_device = SND_DEVICE_IN_VOICE_DMIC_BS;
647 else
648 snd_device = SND_DEVICE_IN_HANDSET_MIC;
649 }
650 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
651 snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
652 } else if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
653 snd_device = SND_DEVICE_IN_BT_SCO_MIC ;
654 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
655 if (my_data->fluence_in_voice_call && my_data->fluence_in_spkr_mode &&
656 my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
657 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF;
658 } else if (my_data->fluence_in_voice_call && my_data->fluence_in_spkr_mode &&
659 my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE) {
660 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS;
661 } else {
662 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
663 }
664 }
665 } else if (source == AUDIO_SOURCE_CAMCORDER) {
666 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
667 in_device & AUDIO_DEVICE_IN_BACK_MIC) {
668 snd_device = SND_DEVICE_IN_CAMCORDER_MIC;
669 }
670 } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) {
671 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
672 if (my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
673 if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
674 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_EF;
675 else if (my_data->fluence_in_voice_rec)
676 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE;
677 } else if (my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE) {
678 if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
679 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_BS;
680 else if (my_data->fluence_in_voice_rec)
681 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE;
682 }
683
684 if (snd_device == SND_DEVICE_NONE) {
685 snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
686 }
687 }
688 } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
689 if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
690 in_device = AUDIO_DEVICE_IN_BACK_MIC;
691 if (adev->active_input) {
692 if (adev->active_input->enable_aec) {
693 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
694 snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
695 } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
696 snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
697 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
698 snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
699 }
700 set_echo_reference(adev->mixer, "SLIM_RX");
701 } else
702 set_echo_reference(adev->mixer, "NONE");
703 }
704 } else if (source == AUDIO_SOURCE_DEFAULT) {
705 goto exit;
706 }
707
708
709 if (snd_device != SND_DEVICE_NONE) {
710 goto exit;
711 }
712
713 if (in_device != AUDIO_DEVICE_NONE &&
714 !(in_device & AUDIO_DEVICE_IN_VOICE_CALL) &&
715 !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) {
716 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
717 snd_device = SND_DEVICE_IN_HANDSET_MIC;
718 } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
719 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
720 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
721 snd_device = SND_DEVICE_IN_HEADSET_MIC;
722 } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
723 snd_device = SND_DEVICE_IN_BT_SCO_MIC ;
724 } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) {
725 snd_device = SND_DEVICE_IN_HDMI_MIC;
726 } else {
727 ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
728 ALOGW("%s: Using default handset-mic", __func__);
729 snd_device = SND_DEVICE_IN_HANDSET_MIC;
730 }
731 } else {
732 if (out_device & AUDIO_DEVICE_OUT_EARPIECE) {
733 snd_device = SND_DEVICE_IN_HANDSET_MIC;
734 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
735 snd_device = SND_DEVICE_IN_HEADSET_MIC;
736 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
737 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
738 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
739 snd_device = SND_DEVICE_IN_HANDSET_MIC;
740 } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
741 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
742 } else if (out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
743 snd_device = SND_DEVICE_IN_HDMI_MIC;
744 } else {
745 ALOGE("%s: Unknown output device(s) %#x", __func__, out_device);
746 ALOGW("%s: Using default handset-mic", __func__);
747 snd_device = SND_DEVICE_IN_HANDSET_MIC;
748 }
749 }
750exit:
751 ALOGV("%s: exit: in_snd_device(%s)", __func__, device_table[snd_device]);
752 return snd_device;
753}
754
755int platform_set_hdmi_channels(void *platform, int channel_count)
756{
757 struct platform_data *my_data = (struct platform_data *)platform;
758 struct audio_device *adev = my_data->adev;
759 struct mixer_ctl *ctl;
760 const char *channel_cnt_str = NULL;
761 const char *mixer_ctl_name = "HDMI_RX Channels";
762 switch (channel_count) {
763 case 8:
764 channel_cnt_str = "Eight"; break;
765 case 7:
766 channel_cnt_str = "Seven"; break;
767 case 6:
768 channel_cnt_str = "Six"; break;
769 case 5:
770 channel_cnt_str = "Five"; break;
771 case 4:
772 channel_cnt_str = "Four"; break;
773 case 3:
774 channel_cnt_str = "Three"; break;
775 default:
776 channel_cnt_str = "Two"; break;
777 }
778 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
779 if (!ctl) {
780 ALOGE("%s: Could not get ctl for mixer cmd - %s",
781 __func__, mixer_ctl_name);
782 return -EINVAL;
783 }
784 ALOGV("HDMI channel count: %s", channel_cnt_str);
785 mixer_ctl_set_enum_by_string(ctl, channel_cnt_str);
786 return 0;
787}
788
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700789int platform_edid_get_max_channels(void *platform)
Eric Laurentb23d5282013-05-14 15:27:20 -0700790{
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700791 struct platform_data *my_data = (struct platform_data *)platform;
792 struct audio_device *adev = my_data->adev;
Eric Laurentb23d5282013-05-14 15:27:20 -0700793 char block[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE];
794 char *sad = block;
795 int num_audio_blocks;
796 int channel_count;
797 int max_channels = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700798 int i, ret, count;
Eric Laurentb23d5282013-05-14 15:27:20 -0700799
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700800 struct mixer_ctl *ctl;
801
802 ctl = mixer_get_ctl_by_name(adev->mixer, AUDIO_DATA_BLOCK_MIXER_CTL);
803 if (!ctl) {
804 ALOGE("%s: Could not get ctl for mixer cmd - %s",
805 __func__, AUDIO_DATA_BLOCK_MIXER_CTL);
Eric Laurentb23d5282013-05-14 15:27:20 -0700806 return 0;
807 }
808
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700809 mixer_ctl_update(ctl);
810
811 count = mixer_ctl_get_num_values(ctl);
Eric Laurentb23d5282013-05-14 15:27:20 -0700812
813 /* Read SAD blocks, clamping the maximum size for safety */
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700814 if (count > (int)sizeof(block))
815 count = (int)sizeof(block);
Eric Laurentb23d5282013-05-14 15:27:20 -0700816
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700817 ret = mixer_ctl_get_array(ctl, block, count);
818 if (ret != 0) {
819 ALOGE("%s: mixer_ctl_get_array() failed to get EDID info", __func__);
820 return 0;
821 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700822
823 /* Calculate the number of SAD blocks */
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700824 num_audio_blocks = count / SAD_BLOCK_SIZE;
Eric Laurentb23d5282013-05-14 15:27:20 -0700825
826 for (i = 0; i < num_audio_blocks; i++) {
827 /* Only consider LPCM blocks */
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700828 if ((sad[0] >> 3) != EDID_FORMAT_LPCM) {
829 sad += 3;
Eric Laurentb23d5282013-05-14 15:27:20 -0700830 continue;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700831 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700832
833 channel_count = (sad[0] & 0x7) + 1;
834 if (channel_count > max_channels)
835 max_channels = channel_count;
836
837 /* Advance to next block */
838 sad += 3;
839 }
840
841 return max_channels;
842}