platform.c revision 9f3065480c81bf01d3af65bfd3da09e1fb74b520
1/* 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/str_parms.h> 25#include <cutils/properties.h> 26#include <audio_hw.h> 27#include <platform_api.h> 28#include "platform.h" 29 30#define MIXER_XML_PATH "/system/etc/mixer_paths.xml" 31#define LIB_ACDB_LOADER "libacdbloader.so" 32#define AUDIO_DATA_BLOCK_MIXER_CTL "HDMI EDID" 33 34#define DUALMIC_CONFIG_NONE 0 /* Target does not contain 2 mics */ 35#define DUALMIC_CONFIG_ENDFIRE 1 36#define DUALMIC_CONFIG_BROADSIDE 2 37 38/* 39 * 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 51/* Retry for delay in FW loading*/ 52#define RETRY_NUMBER 10 53#define RETRY_US 500000 54 55#define MAX_VOL_INDEX 5 56#define MIN_VOL_INDEX 0 57#define percent_to_index(val, min, max) \ 58 ((val) * ((max) - (min)) * 0.01 + (min) + .5) 59 60struct audio_block_header 61{ 62 int reserved; 63 int length; 64}; 65 66typedef void (*acdb_deallocate_t)(); 67typedef int (*acdb_init_t)(); 68typedef void (*acdb_send_audio_cal_t)(int, int); 69typedef void (*acdb_send_voice_cal_t)(int, int); 70 71/* Audio calibration related functions */ 72struct platform_data { 73 struct audio_device *adev; 74 bool fluence_in_spkr_mode; 75 bool fluence_in_voice_call; 76 bool fluence_in_voice_rec; 77 int dualmic_config; 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}, 89 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9}, 90 [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_BT_SCO_WB] = "bt-sco-headset-wb", 111 [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = "voice-handset-tmus", 112 [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = "voice-tty-full-headphones", 113 [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = "voice-tty-vco-headphones", 114 [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = "voice-tty-hco-handset", 115 116 /* Capture sound devices */ 117 [SND_DEVICE_IN_HANDSET_MIC] = "handset-mic", 118 [SND_DEVICE_IN_SPEAKER_MIC] = "speaker-mic", 119 [SND_DEVICE_IN_HEADSET_MIC] = "headset-mic", 120 [SND_DEVICE_IN_HANDSET_MIC_AEC] = "handset-mic", 121 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = "speaker-mic-aec", 122 [SND_DEVICE_IN_HEADSET_MIC_AEC] = "headset-mic", 123 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "voice-speaker-mic", 124 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "voice-headset-mic", 125 [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic", 126 [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic", 127 [SND_DEVICE_IN_BT_SCO_MIC_WB] = "bt-sco-mic-wb", 128 [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic", 129 [SND_DEVICE_IN_VOICE_DMIC_EF] = "voice-dmic-ef", 130 [SND_DEVICE_IN_VOICE_DMIC_BS] = "voice-dmic-bs", 131 [SND_DEVICE_IN_VOICE_DMIC_EF_TMUS] = "voice-dmic-ef-tmus", 132 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF] = "voice-speaker-dmic-ef", 133 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS] = "voice-speaker-dmic-bs", 134 [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = "voice-tty-full-headset-mic", 135 [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = "voice-tty-vco-handset-mic", 136 [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = "voice-tty-hco-headset-mic", 137 [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic", 138 [SND_DEVICE_IN_VOICE_REC_DMIC_EF] = "voice-rec-dmic-ef", 139 [SND_DEVICE_IN_VOICE_REC_DMIC_BS] = "voice-rec-dmic-bs", 140 [SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE] = "voice-rec-dmic-ef-fluence", 141 [SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE] = "voice-rec-dmic-bs-fluence", 142}; 143 144/* ACDB IDs (audio DSP path configuration IDs) for each sound device */ 145static const int acdb_device_table[SND_DEVICE_MAX] = { 146 [SND_DEVICE_NONE] = -1, 147 [SND_DEVICE_OUT_HANDSET] = 7, 148 [SND_DEVICE_OUT_SPEAKER] = 15, 149 [SND_DEVICE_OUT_SPEAKER_REVERSE] = 15, 150 [SND_DEVICE_OUT_HEADPHONES] = 10, 151 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = 10, 152 [SND_DEVICE_OUT_VOICE_HANDSET] = 7, 153 [SND_DEVICE_OUT_VOICE_SPEAKER] = 15, 154 [SND_DEVICE_OUT_VOICE_HEADPHONES] = 10, 155 [SND_DEVICE_OUT_HDMI] = 18, 156 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 15, 157 [SND_DEVICE_OUT_BT_SCO] = 22, 158 [SND_DEVICE_OUT_BT_SCO_WB] = 39, 159 [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = 88, 160 [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = 17, 161 [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = 17, 162 [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = 37, 163 164 [SND_DEVICE_IN_HANDSET_MIC] = 4, 165 [SND_DEVICE_IN_SPEAKER_MIC] = 4, /* ToDo: Check if this needs to changed to 11 */ 166 [SND_DEVICE_IN_HEADSET_MIC] = 8, 167 [SND_DEVICE_IN_HANDSET_MIC_AEC] = 40, 168 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = 42, 169 [SND_DEVICE_IN_HEADSET_MIC_AEC] = 47, 170 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = 11, 171 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = 8, 172 [SND_DEVICE_IN_HDMI_MIC] = 4, 173 [SND_DEVICE_IN_BT_SCO_MIC] = 21, 174 [SND_DEVICE_IN_BT_SCO_MIC_WB] = 38, 175 [SND_DEVICE_IN_CAMCORDER_MIC] = 61, 176 [SND_DEVICE_IN_VOICE_DMIC_EF] = 41, 177 [SND_DEVICE_IN_VOICE_DMIC_BS] = 5, 178 [SND_DEVICE_IN_VOICE_DMIC_EF_TMUS] = 89, 179 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF] = 43, 180 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS] = 12, 181 [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = 16, 182 [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = 36, 183 [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = 16, 184 [SND_DEVICE_IN_VOICE_REC_MIC] = 62, 185 /* TODO: Update with proper acdb ids */ 186 [SND_DEVICE_IN_VOICE_REC_DMIC_EF] = 62, 187 [SND_DEVICE_IN_VOICE_REC_DMIC_BS] = 62, 188 [SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE] = 6, 189 [SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE] = 5, 190}; 191 192#define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL) 193#define LOW_LATENCY_PLATFORM_DELAY (13*1000LL) 194 195static pthread_once_t check_op_once_ctl = PTHREAD_ONCE_INIT; 196static bool is_tmus = false; 197 198static void check_operator() 199{ 200 char value[PROPERTY_VALUE_MAX]; 201 int mccmnc; 202 property_get("gsm.sim.operator.numeric",value,"0"); 203 mccmnc = atoi(value); 204 ALOGD("%s: tmus mccmnc %d", __func__, mccmnc); 205 switch(mccmnc) { 206 /* TMUS MCC(310), MNC(490, 260, 026) */ 207 case 310490: 208 case 310260: 209 case 310026: 210 /* Add new TMUS MNC(800, 660, 580, 310, 270, 250, 240, 230, 220, 210, 200, 160) */ 211 case 310800: 212 case 310660: 213 case 310580: 214 case 310310: 215 case 310270: 216 case 310250: 217 case 310240: 218 case 310230: 219 case 310220: 220 case 310210: 221 case 310200: 222 case 310160: 223 is_tmus = true; 224 break; 225 } 226} 227 228bool is_operator_tmus() 229{ 230 pthread_once(&check_op_once_ctl, check_operator); 231 return is_tmus; 232} 233 234static int set_volume_values(int type, int volume, int* values) 235{ 236 values[0] = volume; 237 values[1] = ALL_SESSION_VSID; 238 239 switch(type) { 240 case VOLUME_SET: 241 values[2] = DEFAULT_VOLUME_RAMP_DURATION_MS; 242 break; 243 case MUTE_SET: 244 values[2] = DEFAULT_MUTE_RAMP_DURATION; 245 break; 246 default: 247 return -EINVAL; 248 } 249 return 0; 250} 251 252static int set_echo_reference(struct mixer *mixer, const char* ec_ref) 253{ 254 struct mixer_ctl *ctl; 255 const char *mixer_ctl_name = "EC_REF_RX"; 256 257 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name); 258 if (!ctl) { 259 ALOGE("%s: Could not get ctl for mixer cmd - %s", 260 __func__, mixer_ctl_name); 261 return -EINVAL; 262 } 263 ALOGV("Setting EC Reference: %s", ec_ref); 264 mixer_ctl_set_enum_by_string(ctl, ec_ref); 265 return 0; 266} 267 268void *platform_init(struct audio_device *adev) 269{ 270 char value[PROPERTY_VALUE_MAX]; 271 struct platform_data *my_data; 272 int retry_num = 0; 273 274 adev->mixer = mixer_open(MIXER_CARD); 275 276 while (!adev->mixer && retry_num < RETRY_NUMBER) { 277 usleep(RETRY_US); 278 adev->mixer = mixer_open(MIXER_CARD); 279 retry_num++; 280 } 281 282 if (!adev->mixer) { 283 ALOGE("Unable to open the mixer, aborting."); 284 return NULL; 285 } 286 287 adev->audio_route = audio_route_init(MIXER_CARD, MIXER_XML_PATH); 288 if (!adev->audio_route) { 289 ALOGE("%s: Failed to init audio route controls, aborting.", __func__); 290 return NULL; 291 } 292 293 my_data = calloc(1, sizeof(struct platform_data)); 294 295 my_data->adev = adev; 296 my_data->dualmic_config = DUALMIC_CONFIG_NONE; 297 my_data->fluence_in_spkr_mode = false; 298 my_data->fluence_in_voice_call = false; 299 my_data->fluence_in_voice_rec = false; 300 301 property_get("persist.audio.dualmic.config",value,""); 302 if (!strcmp("broadside", value)) { 303 my_data->dualmic_config = DUALMIC_CONFIG_BROADSIDE; 304 adev->acdb_settings |= DMIC_FLAG; 305 } else if (!strcmp("endfire", value)) { 306 my_data->dualmic_config = DUALMIC_CONFIG_ENDFIRE; 307 adev->acdb_settings |= DMIC_FLAG; 308 } 309 310 if (my_data->dualmic_config != DUALMIC_CONFIG_NONE) { 311 property_get("persist.audio.fluence.voicecall",value,""); 312 if (!strcmp("true", value)) { 313 my_data->fluence_in_voice_call = true; 314 } 315 316 property_get("persist.audio.fluence.voicerec",value,""); 317 if (!strcmp("true", value)) { 318 my_data->fluence_in_voice_rec = true; 319 } 320 321 property_get("persist.audio.fluence.speaker",value,""); 322 if (!strcmp("true", value)) { 323 my_data->fluence_in_spkr_mode = true; 324 } 325 } 326 327 my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW); 328 if (my_data->acdb_handle == NULL) { 329 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_ACDB_LOADER); 330 } else { 331 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_ACDB_LOADER); 332 my_data->acdb_deallocate = (acdb_deallocate_t)dlsym(my_data->acdb_handle, 333 "acdb_loader_deallocate_ACDB"); 334 my_data->acdb_send_audio_cal = (acdb_send_audio_cal_t)dlsym(my_data->acdb_handle, 335 "acdb_loader_send_audio_cal"); 336 if (!my_data->acdb_send_audio_cal) 337 ALOGW("%s: Could not find the symbol acdb_send_audio_cal from %s", 338 __func__, LIB_ACDB_LOADER); 339 my_data->acdb_send_voice_cal = (acdb_send_voice_cal_t)dlsym(my_data->acdb_handle, 340 "acdb_loader_send_voice_cal"); 341 my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle, 342 "acdb_loader_init_ACDB"); 343 if (my_data->acdb_init == NULL) 344 ALOGE("%s: dlsym error %s for acdb_loader_init_ACDB", __func__, dlerror()); 345 else 346 my_data->acdb_init(); 347 } 348 349 return my_data; 350} 351 352void platform_deinit(void *platform) 353{ 354 free(platform); 355} 356 357const char *platform_get_snd_device_name(snd_device_t snd_device) 358{ 359 if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX) 360 return device_table[snd_device]; 361 else 362 return ""; 363} 364 365void platform_add_backend_name(char *mixer_path, snd_device_t snd_device) 366{ 367 if (snd_device == SND_DEVICE_IN_BT_SCO_MIC) 368 strcat(mixer_path, " bt-sco"); 369 else if(snd_device == SND_DEVICE_OUT_BT_SCO) 370 strcat(mixer_path, " bt-sco"); 371 else if (snd_device == SND_DEVICE_OUT_HDMI) 372 strcat(mixer_path, " hdmi"); 373 else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HDMI) 374 strcat(mixer_path, " speaker-and-hdmi"); 375 else if (snd_device == SND_DEVICE_OUT_BT_SCO_WB || 376 snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB) 377 strcat(mixer_path, " bt-sco-wb"); 378} 379 380int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type) 381{ 382 int device_id; 383 if (device_type == PCM_PLAYBACK) 384 device_id = pcm_device_table[usecase][0]; 385 else 386 device_id = pcm_device_table[usecase][1]; 387 return device_id; 388} 389 390int platform_send_audio_calibration(void *platform, snd_device_t snd_device) 391{ 392 struct platform_data *my_data = (struct platform_data *)platform; 393 int acdb_dev_id, acdb_dev_type; 394 395 acdb_dev_id = acdb_device_table[snd_device]; 396 if (acdb_dev_id < 0) { 397 ALOGE("%s: Could not find acdb id for device(%d)", 398 __func__, snd_device); 399 return -EINVAL; 400 } 401 if (my_data->acdb_send_audio_cal) { 402 ("%s: sending audio calibration for snd_device(%d) acdb_id(%d)", 403 __func__, snd_device, acdb_dev_id); 404 if (snd_device >= SND_DEVICE_OUT_BEGIN && 405 snd_device < SND_DEVICE_OUT_END) 406 acdb_dev_type = ACDB_DEV_TYPE_OUT; 407 else 408 acdb_dev_type = ACDB_DEV_TYPE_IN; 409 my_data->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type); 410 } 411 return 0; 412} 413 414int platform_switch_voice_call_device_pre(void *platform) 415{ 416 return 0; 417} 418 419int platform_switch_voice_call_device_post(void *platform, 420 snd_device_t out_snd_device, 421 snd_device_t in_snd_device) 422{ 423 struct platform_data *my_data = (struct platform_data *)platform; 424 int acdb_rx_id, acdb_tx_id; 425 426 if (my_data->acdb_send_voice_cal == NULL) { 427 ALOGE("%s: dlsym error for acdb_send_voice_call", __func__); 428 } else { 429 acdb_rx_id = acdb_device_table[out_snd_device]; 430 acdb_tx_id = acdb_device_table[in_snd_device]; 431 432 if (acdb_rx_id > 0 && acdb_tx_id > 0) 433 my_data->acdb_send_voice_cal(acdb_rx_id, acdb_tx_id); 434 else 435 ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__, 436 acdb_rx_id, acdb_tx_id); 437 } 438 439 return 0; 440} 441 442int platform_start_voice_call(void *platform) 443{ 444 return 0; 445} 446 447int platform_stop_voice_call(void *platform) 448{ 449 return 0; 450} 451 452int platform_set_voice_volume(void *platform, int volume) 453{ 454 struct platform_data *my_data = (struct platform_data *)platform; 455 struct audio_device *adev = my_data->adev; 456 struct mixer_ctl *ctl; 457 const char *mixer_ctl_name = "Voice Rx Gain"; 458 int values[VOLUME_CTL_PARAM_NUM]; 459 int ret = 0; 460 461 // Voice volume levels are mapped to adsp volume levels as follows. 462 // 100 -> 5, 80 -> 4, 60 -> 3, 40 -> 2, 20 -> 1 0 -> 0 463 // But this values don't changed in kernel. So, below change is need. 464 volume = (int)percent_to_index(volume, MIN_VOL_INDEX, MAX_VOL_INDEX); 465 466 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name); 467 if (!ctl) { 468 ALOGE("%s: Could not get ctl for mixer cmd - %s", 469 __func__, mixer_ctl_name); 470 return -EINVAL; 471 } 472 ret = set_volume_values(VOLUME_SET, volume, values); 473 if (ret < 0) { 474 ALOGV("%s: failed setting volume by incorrect type", __func__); 475 return -EINVAL; 476 } 477 ret = mixer_ctl_set_array(ctl, values, sizeof(values)/sizeof(int)); 478 if (ret < 0) { 479 ALOGV("%s: failed set mixer ctl by %d", __func__, ret); 480 return -EINVAL; 481 } 482 483 return 0; 484} 485 486int platform_set_mic_mute(void *platform, bool state) 487{ 488 struct platform_data *my_data = (struct platform_data *)platform; 489 struct audio_device *adev = my_data->adev; 490 struct mixer_ctl *ctl; 491 const char *mixer_ctl_name = "Voice Tx Mute"; 492 int values[VOLUME_CTL_PARAM_NUM]; 493 int ret = 0; 494 495 if (adev->mode == AUDIO_MODE_IN_CALL) { 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 } 502 ALOGV("Setting mic mute: %d", state); 503 ret = set_volume_values(MUTE_SET, state, values); 504 if (ret < 0) { 505 ALOGV("%s: failed setting mute by incorrect type", __func__); 506 return -EINVAL; 507 } 508 ret = mixer_ctl_set_array(ctl, values, sizeof(values)/sizeof(int)); 509 if (ret < 0) { 510 ALOGV("%s: failed set mixer ctl by %d", __func__, ret); 511 return -EINVAL; 512 } 513 } 514 515 return 0; 516} 517 518snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices) 519{ 520 struct platform_data *my_data = (struct platform_data *)platform; 521 struct audio_device *adev = my_data->adev; 522 audio_mode_t mode = adev->mode; 523 snd_device_t snd_device = SND_DEVICE_NONE; 524 525 ALOGV("%s: enter: output devices(%#x)", __func__, devices); 526 if (devices == AUDIO_DEVICE_NONE || 527 devices & AUDIO_DEVICE_BIT_IN) { 528 ALOGV("%s: Invalid output devices (%#x)", __func__, devices); 529 goto exit; 530 } 531 532 if (mode == AUDIO_MODE_IN_CALL) { 533 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE || 534 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) { 535 if (adev->tty_mode == TTY_MODE_FULL) 536 snd_device = SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES; 537 else if (adev->tty_mode == TTY_MODE_VCO) 538 snd_device = SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES; 539 else if (adev->tty_mode == TTY_MODE_HCO) 540 snd_device = SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET; 541 else 542 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES; 543 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) { 544 if (adev->bt_wb_speech_enabled) { 545 snd_device = SND_DEVICE_OUT_BT_SCO_WB; 546 } else { 547 snd_device = SND_DEVICE_OUT_BT_SCO; 548 } 549 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) { 550 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER; 551 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) { 552 if (is_operator_tmus()) 553 snd_device = SND_DEVICE_OUT_VOICE_HANDSET_TMUS; 554 else 555 snd_device = SND_DEVICE_OUT_HANDSET; 556 } 557 if (snd_device != SND_DEVICE_NONE) { 558 goto exit; 559 } 560 } 561 562 if (popcount(devices) == 2) { 563 if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE | 564 AUDIO_DEVICE_OUT_SPEAKER)) { 565 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES; 566 } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET | 567 AUDIO_DEVICE_OUT_SPEAKER)) { 568 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES; 569 } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL | 570 AUDIO_DEVICE_OUT_SPEAKER)) { 571 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI; 572 } else { 573 ALOGE("%s: Invalid combo device(%#x)", __func__, devices); 574 goto exit; 575 } 576 if (snd_device != SND_DEVICE_NONE) { 577 goto exit; 578 } 579 } 580 581 if (popcount(devices) != 1) { 582 ALOGE("%s: Invalid output devices(%#x)", __func__, devices); 583 goto exit; 584 } 585 586 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE || 587 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) { 588 snd_device = SND_DEVICE_OUT_HEADPHONES; 589 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) { 590 if (adev->speaker_lr_swap) 591 snd_device = SND_DEVICE_OUT_SPEAKER_REVERSE; 592 else 593 snd_device = SND_DEVICE_OUT_SPEAKER; 594 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) { 595 if (adev->bt_wb_speech_enabled) { 596 snd_device = SND_DEVICE_OUT_BT_SCO_WB; 597 } else { 598 snd_device = SND_DEVICE_OUT_BT_SCO; 599 } 600 } else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) { 601 snd_device = SND_DEVICE_OUT_HDMI ; 602 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) { 603 snd_device = SND_DEVICE_OUT_HANDSET; 604 } else { 605 ALOGE("%s: Unknown device(s) %#x", __func__, devices); 606 } 607exit: 608 ALOGV("%s: exit: snd_device(%s)", __func__, device_table[snd_device]); 609 return snd_device; 610} 611 612snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device) 613{ 614 struct platform_data *my_data = (struct platform_data *)platform; 615 struct audio_device *adev = my_data->adev; 616 audio_source_t source = (adev->active_input == NULL) ? 617 AUDIO_SOURCE_DEFAULT : adev->active_input->source; 618 619 audio_mode_t mode = adev->mode; 620 audio_devices_t in_device = ((adev->active_input == NULL) ? 621 AUDIO_DEVICE_NONE : adev->active_input->device) 622 & ~AUDIO_DEVICE_BIT_IN; 623 audio_channel_mask_t channel_mask = (adev->active_input == NULL) ? 624 AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask; 625 snd_device_t snd_device = SND_DEVICE_NONE; 626 627 ALOGV("%s: enter: out_device(%#x) in_device(%#x)", 628 __func__, out_device, in_device); 629 if (mode == AUDIO_MODE_IN_CALL) { 630 if (out_device == AUDIO_DEVICE_NONE) { 631 ALOGE("%s: No output device set for voice call", __func__); 632 goto exit; 633 } 634 if (adev->tty_mode != TTY_MODE_OFF) { 635 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE || 636 out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) { 637 switch (adev->tty_mode) { 638 case TTY_MODE_FULL: 639 snd_device = SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC; 640 break; 641 case TTY_MODE_VCO: 642 snd_device = SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC; 643 break; 644 case TTY_MODE_HCO: 645 snd_device = SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC; 646 break; 647 default: 648 ALOGE("%s: Invalid TTY mode (%#x)", __func__, adev->tty_mode); 649 } 650 goto exit; 651 } 652 } 653 if (out_device & AUDIO_DEVICE_OUT_EARPIECE || 654 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) { 655 if (my_data->fluence_in_voice_call == false) { 656 snd_device = SND_DEVICE_IN_HANDSET_MIC; 657 } else { 658 if (my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) { 659 if (is_operator_tmus()) 660 snd_device = SND_DEVICE_IN_VOICE_DMIC_EF_TMUS; 661 else 662 snd_device = SND_DEVICE_IN_VOICE_DMIC_EF; 663 } else if(my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE) 664 snd_device = SND_DEVICE_IN_VOICE_DMIC_BS; 665 else 666 snd_device = SND_DEVICE_IN_HANDSET_MIC; 667 } 668 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) { 669 snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC; 670 } else if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) { 671 if (adev->bt_wb_speech_enabled) { 672 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB; 673 } else { 674 snd_device = SND_DEVICE_IN_BT_SCO_MIC; 675 } 676 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) { 677 if (my_data->fluence_in_voice_call && my_data->fluence_in_spkr_mode && 678 my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) { 679 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF; 680 } else if (my_data->fluence_in_voice_call && my_data->fluence_in_spkr_mode && 681 my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE) { 682 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS; 683 } else { 684 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC; 685 } 686 } 687 } else if (source == AUDIO_SOURCE_CAMCORDER) { 688 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC || 689 in_device & AUDIO_DEVICE_IN_BACK_MIC) { 690 snd_device = SND_DEVICE_IN_CAMCORDER_MIC; 691 } 692 } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) { 693 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) { 694 if (my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) { 695 if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK) 696 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_EF; 697 else if (my_data->fluence_in_voice_rec) 698 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE; 699 } else if (my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE) { 700 if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK) 701 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_BS; 702 else if (my_data->fluence_in_voice_rec) 703 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE; 704 } 705 706 if (snd_device == SND_DEVICE_NONE) { 707 snd_device = SND_DEVICE_IN_VOICE_REC_MIC; 708 } 709 } 710 } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION) { 711 if (out_device & AUDIO_DEVICE_OUT_SPEAKER) 712 in_device = AUDIO_DEVICE_IN_BACK_MIC; 713 if (adev->active_input) { 714 if (adev->active_input->enable_aec) { 715 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) { 716 snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC; 717 } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) { 718 snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC; 719 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) { 720 snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC; 721 } 722 set_echo_reference(adev->mixer, "SLIM_RX"); 723 } else 724 set_echo_reference(adev->mixer, "NONE"); 725 } 726 } else if (source == AUDIO_SOURCE_DEFAULT) { 727 goto exit; 728 } 729 730 731 if (snd_device != SND_DEVICE_NONE) { 732 goto exit; 733 } 734 735 if (in_device != AUDIO_DEVICE_NONE && 736 !(in_device & AUDIO_DEVICE_IN_VOICE_CALL) && 737 !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) { 738 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) { 739 snd_device = SND_DEVICE_IN_HANDSET_MIC; 740 } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) { 741 snd_device = SND_DEVICE_IN_SPEAKER_MIC; 742 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) { 743 snd_device = SND_DEVICE_IN_HEADSET_MIC; 744 } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) { 745 if (adev->bt_wb_speech_enabled) { 746 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB; 747 } else { 748 snd_device = SND_DEVICE_IN_BT_SCO_MIC; 749 } 750 } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) { 751 snd_device = SND_DEVICE_IN_HDMI_MIC; 752 } else { 753 ALOGE("%s: Unknown input device(s) %#x", __func__, in_device); 754 ALOGW("%s: Using default handset-mic", __func__); 755 snd_device = SND_DEVICE_IN_HANDSET_MIC; 756 } 757 } else { 758 if (out_device & AUDIO_DEVICE_OUT_EARPIECE) { 759 snd_device = SND_DEVICE_IN_HANDSET_MIC; 760 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) { 761 snd_device = SND_DEVICE_IN_HEADSET_MIC; 762 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) { 763 snd_device = SND_DEVICE_IN_SPEAKER_MIC; 764 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) { 765 snd_device = SND_DEVICE_IN_HANDSET_MIC; 766 } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) { 767 if (adev->bt_wb_speech_enabled) { 768 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB; 769 } else { 770 snd_device = SND_DEVICE_IN_BT_SCO_MIC; 771 } 772 } else if (out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL) { 773 snd_device = SND_DEVICE_IN_HDMI_MIC; 774 } else { 775 ALOGE("%s: Unknown output device(s) %#x", __func__, out_device); 776 ALOGW("%s: Using default handset-mic", __func__); 777 snd_device = SND_DEVICE_IN_HANDSET_MIC; 778 } 779 } 780exit: 781 ALOGV("%s: exit: in_snd_device(%s)", __func__, device_table[snd_device]); 782 return snd_device; 783} 784 785int platform_set_hdmi_channels(void *platform, int channel_count) 786{ 787 struct platform_data *my_data = (struct platform_data *)platform; 788 struct audio_device *adev = my_data->adev; 789 struct mixer_ctl *ctl; 790 const char *channel_cnt_str = NULL; 791 const char *mixer_ctl_name = "HDMI_RX Channels"; 792 switch (channel_count) { 793 case 8: 794 channel_cnt_str = "Eight"; break; 795 case 7: 796 channel_cnt_str = "Seven"; break; 797 case 6: 798 channel_cnt_str = "Six"; break; 799 case 5: 800 channel_cnt_str = "Five"; break; 801 case 4: 802 channel_cnt_str = "Four"; break; 803 case 3: 804 channel_cnt_str = "Three"; break; 805 default: 806 channel_cnt_str = "Two"; break; 807 } 808 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name); 809 if (!ctl) { 810 ALOGE("%s: Could not get ctl for mixer cmd - %s", 811 __func__, mixer_ctl_name); 812 return -EINVAL; 813 } 814 ALOGV("HDMI channel count: %s", channel_cnt_str); 815 mixer_ctl_set_enum_by_string(ctl, channel_cnt_str); 816 return 0; 817} 818 819int platform_edid_get_max_channels(void *platform) 820{ 821 struct platform_data *my_data = (struct platform_data *)platform; 822 struct audio_device *adev = my_data->adev; 823 char block[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE]; 824 char *sad = block; 825 int num_audio_blocks; 826 int channel_count; 827 int max_channels = 0; 828 int i, ret, count; 829 830 struct mixer_ctl *ctl; 831 832 ctl = mixer_get_ctl_by_name(adev->mixer, AUDIO_DATA_BLOCK_MIXER_CTL); 833 if (!ctl) { 834 ALOGE("%s: Could not get ctl for mixer cmd - %s", 835 __func__, AUDIO_DATA_BLOCK_MIXER_CTL); 836 return 0; 837 } 838 839 mixer_ctl_update(ctl); 840 841 count = mixer_ctl_get_num_values(ctl); 842 843 /* Read SAD blocks, clamping the maximum size for safety */ 844 if (count > (int)sizeof(block)) 845 count = (int)sizeof(block); 846 847 ret = mixer_ctl_get_array(ctl, block, count); 848 if (ret != 0) { 849 ALOGE("%s: mixer_ctl_get_array() failed to get EDID info", __func__); 850 return 0; 851 } 852 853 /* Calculate the number of SAD blocks */ 854 num_audio_blocks = count / SAD_BLOCK_SIZE; 855 856 for (i = 0; i < num_audio_blocks; i++) { 857 /* Only consider LPCM blocks */ 858 if ((sad[0] >> 3) != EDID_FORMAT_LPCM) { 859 sad += 3; 860 continue; 861 } 862 863 channel_count = (sad[0] & 0x7) + 1; 864 if (channel_count > max_channels) 865 max_channels = channel_count; 866 867 /* Advance to next block */ 868 sad += 3; 869 } 870 871 return max_channels; 872} 873 874/* Delay in Us */ 875int64_t platform_render_latency(audio_usecase_t usecase) 876{ 877 switch (usecase) { 878 case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER: 879 return DEEP_BUFFER_PLATFORM_DELAY; 880 case USECASE_AUDIO_PLAYBACK_LOW_LATENCY: 881 return LOW_LATENCY_PLATFORM_DELAY; 882 default: 883 return 0; 884 } 885} 886