1 /* 2 * Copyright (C) 2013-2014 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 "msm8960_platform" 18 /*#define LOG_NDEBUG 0*/ 19 #define LOG_NDDEBUG 0 20 21 #include <stdlib.h> 22 #include <dlfcn.h> 23 #include <log/log.h> 24 #include <cutils/properties.h> 25 #include <audio_hw.h> 26 #include <platform_api.h> 27 #include "platform.h" 28 #include "audio_extn.h" 29 30 #define LIB_ACDB_LOADER "libacdbloader.so" 31 #define LIB_CSD_CLIENT "libcsd-client.so" 32 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 /* 38 * This is the sysfs path for the HDMI audio data block 39 */ 40 #define AUDIO_DATA_BLOCK_PATH "/sys/class/graphics/fb1/audio_data_block" 41 #define MIXER_XML_PATH "/system/etc/mixer_paths.xml" 42 43 /* 44 * This file will have a maximum of 38 bytes: 45 * 46 * 4 bytes: number of audio blocks 47 * 4 bytes: total length of Short Audio Descriptor (SAD) blocks 48 * Maximum 10 * 3 bytes: SAD blocks 49 */ 50 #define MAX_SAD_BLOCKS 10 51 #define SAD_BLOCK_SIZE 3 52 53 /* EDID format ID for LPCM audio */ 54 #define EDID_FORMAT_LPCM 1 55 56 struct audio_block_header 57 { 58 int reserved; 59 int length; 60 }; 61 62 63 typedef void (*acdb_deallocate_t)(); 64 typedef int (*acdb_init_t)(); 65 typedef void (*acdb_send_audio_cal_t)(int, int); 66 typedef void (*acdb_send_voice_cal_t)(int, int); 67 68 typedef int (*csd_client_init_t)(); 69 typedef int (*csd_client_deinit_t)(); 70 typedef int (*csd_disable_device_t)(); 71 typedef int (*csd_enable_device_t)(int, int, uint32_t); 72 typedef int (*csd_volume_t)(int); 73 typedef int (*csd_mic_mute_t)(int); 74 typedef int (*csd_start_voice_t)(); 75 typedef int (*csd_stop_voice_t)(); 76 77 78 /* Audio calibration related functions */ 79 struct 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; 84 int dualmic_config; 85 bool speaker_lr_swap; 86 87 void *acdb_handle; 88 acdb_init_t acdb_init; 89 acdb_deallocate_t acdb_deallocate; 90 acdb_send_audio_cal_t acdb_send_audio_cal; 91 acdb_send_voice_cal_t acdb_send_voice_cal; 92 93 /* CSD Client related functions for voice call */ 94 void *csd_client; 95 csd_client_init_t csd_client_init; 96 csd_client_deinit_t csd_client_deinit; 97 csd_disable_device_t csd_disable_device; 98 csd_enable_device_t csd_enable_device; 99 csd_volume_t csd_volume; 100 csd_mic_mute_t csd_mic_mute; 101 csd_start_voice_t csd_start_voice; 102 csd_stop_voice_t csd_stop_voice; 103 }; 104 105 static const int pcm_device_table[AUDIO_USECASE_MAX][2] = { 106 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0}, 107 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {14, 14}, 108 [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1}, 109 [USECASE_AUDIO_RECORD] = {0, 0}, 110 [USECASE_AUDIO_RECORD_LOW_LATENCY] = {14, 14}, 111 [USECASE_VOICE_CALL] = {12, 12}, 112 }; 113 114 /* Array to store sound devices */ 115 static const char * const device_table[SND_DEVICE_MAX] = { 116 [SND_DEVICE_NONE] = "none", 117 /* Playback sound devices */ 118 [SND_DEVICE_OUT_HANDSET] = "handset", 119 [SND_DEVICE_OUT_SPEAKER] = "speaker", 120 [SND_DEVICE_OUT_SPEAKER_REVERSE] = "speaker-reverse", 121 [SND_DEVICE_OUT_SPEAKER_SAFE] = "speaker-safe", 122 [SND_DEVICE_OUT_HEADPHONES] = "headphones", 123 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones", 124 [SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker", 125 [SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones", 126 [SND_DEVICE_OUT_HDMI] = "hdmi", 127 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi", 128 [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset", 129 [SND_DEVICE_OUT_BT_SCO_WB] = "bt-sco-headset-wb", 130 [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = "voice-handset-tmus", 131 [SND_DEVICE_OUT_VOICE_HANDSET] = "voice-handset-tmus", 132 [SND_DEVICE_OUT_VOICE_HAC_HANDSET] = "voice-handset-tmus", 133 [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = "voice-tty-full-headphones", 134 [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = "voice-tty-vco-headphones", 135 [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = "voice-tty-hco-handset", 136 [SND_DEVICE_OUT_USB_HEADSET] = "usb-headset", 137 [SND_DEVICE_OUT_USB_HEADPHONES] = "usb-headphones", 138 [SND_DEVICE_OUT_VOICE_USB_HEADSET] = "usb-headset", 139 [SND_DEVICE_OUT_VOICE_USB_HEADPHONES] = "usb-headphones", 140 141 142 /* Capture sound devices */ 143 [SND_DEVICE_IN_HANDSET_MIC] = "handset-mic", 144 [SND_DEVICE_IN_SPEAKER_MIC] = "speaker-mic", 145 [SND_DEVICE_IN_HEADSET_MIC] = "headset-mic", 146 [SND_DEVICE_IN_HANDSET_MIC_AEC] = "handset-mic", 147 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = "voice-speaker-mic", 148 [SND_DEVICE_IN_HEADSET_MIC_AEC] = "headset-mic", 149 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "voice-speaker-mic", 150 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "voice-headset-mic", 151 [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic", 152 [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic", 153 [SND_DEVICE_IN_BT_SCO_MIC_WB] = "bt-sco-mic-wb", 154 [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic", 155 [SND_DEVICE_IN_VOICE_DMIC_EF] = "voice-dmic-ef", 156 [SND_DEVICE_IN_VOICE_DMIC_BS] = "voice-dmic-bs", 157 [SND_DEVICE_IN_VOICE_DMIC_EF_TMUS] = "voice-dmic-ef-tmus", 158 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF] = "voice-speaker-dmic-ef", 159 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS] = "voice-speaker-dmic-bs", 160 [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = "voice-tty-full-headset-mic", 161 [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = "voice-tty-vco-handset-mic", 162 [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = "voice-tty-hco-headset-mic", 163 [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic", 164 [SND_DEVICE_IN_VOICE_REC_DMIC_EF] = "voice-rec-dmic-ef", 165 [SND_DEVICE_IN_VOICE_REC_DMIC_BS] = "voice-rec-dmic-bs", 166 [SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE] = "voice-rec-dmic-ef-fluence", 167 [SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE] = "voice-rec-dmic-bs-fluence", 168 }; 169 170 /* ACDB IDs (audio DSP path configuration IDs) for each sound device */ 171 static const int acdb_device_table[SND_DEVICE_MAX] = { 172 [SND_DEVICE_NONE] = -1, 173 [SND_DEVICE_OUT_HANDSET] = 7, 174 [SND_DEVICE_OUT_SPEAKER] = 14, 175 [SND_DEVICE_OUT_SPEAKER_REVERSE] = 14, 176 [SND_DEVICE_OUT_SPEAKER_SAFE] = 14, 177 [SND_DEVICE_OUT_HEADPHONES] = 10, 178 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = 10, 179 [SND_DEVICE_OUT_VOICE_SPEAKER] = 14, 180 [SND_DEVICE_OUT_VOICE_HEADPHONES] = 10, 181 [SND_DEVICE_OUT_HDMI] = 18, 182 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 14, 183 [SND_DEVICE_OUT_BT_SCO] = 22, 184 [SND_DEVICE_OUT_BT_SCO_WB] = 39, 185 [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = 81, 186 [SND_DEVICE_OUT_VOICE_HANDSET] = 81, 187 [SND_DEVICE_OUT_VOICE_HAC_HANDSET] = 81, 188 [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = 17, 189 [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = 17, 190 [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = 37, 191 [SND_DEVICE_OUT_USB_HEADSET] = 45, 192 [SND_DEVICE_OUT_USB_HEADPHONES] = 45, 193 [SND_DEVICE_OUT_VOICE_USB_HEADSET] = 45, 194 [SND_DEVICE_OUT_VOICE_USB_HEADPHONES] = 45, 195 196 [SND_DEVICE_IN_HANDSET_MIC] = 4, 197 [SND_DEVICE_IN_SPEAKER_MIC] = 4, 198 [SND_DEVICE_IN_HEADSET_MIC] = 8, 199 [SND_DEVICE_IN_HANDSET_MIC_AEC] = 40, 200 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = 42, 201 [SND_DEVICE_IN_HEADSET_MIC_AEC] = 47, 202 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = 11, 203 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = 8, 204 [SND_DEVICE_IN_HDMI_MIC] = 4, 205 [SND_DEVICE_IN_BT_SCO_MIC] = 21, 206 [SND_DEVICE_IN_BT_SCO_MIC_WB] = 38, 207 [SND_DEVICE_IN_CAMCORDER_MIC] = 61, 208 [SND_DEVICE_IN_VOICE_DMIC_EF] = 6, 209 [SND_DEVICE_IN_VOICE_DMIC_BS] = 5, 210 [SND_DEVICE_IN_VOICE_DMIC_EF_TMUS] = 91, 211 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF] = 13, 212 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS] = 12, 213 [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = 16, 214 [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = 36, 215 [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = 16, 216 [SND_DEVICE_IN_VOICE_REC_MIC] = 62, 217 /* TODO: Update with proper acdb ids */ 218 [SND_DEVICE_IN_VOICE_REC_DMIC_EF] = 62, 219 [SND_DEVICE_IN_VOICE_REC_DMIC_BS] = 62, 220 [SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE] = 6, 221 [SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE] = 5, 222 }; 223 224 #define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL) 225 #define LOW_LATENCY_PLATFORM_DELAY (13*1000LL) 226 227 static pthread_once_t check_op_once_ctl = PTHREAD_ONCE_INIT; 228 static bool is_tmus = false; 229 230 static void check_operator() 231 { 232 char value[PROPERTY_VALUE_MAX]; 233 int mccmnc; 234 property_get("gsm.sim.operator.numeric",value,"0"); 235 mccmnc = atoi(value); 236 ALOGD("%s: tmus mccmnc %d", __func__, mccmnc); 237 switch(mccmnc) { 238 /* TMUS MCC(310), MNC(490, 260, 026) */ 239 case 310490: 240 case 310260: 241 case 310026: 242 is_tmus = true; 243 break; 244 } 245 } 246 247 bool is_operator_tmus() 248 { 249 pthread_once(&check_op_once_ctl, check_operator); 250 return is_tmus; 251 } 252 253 static int set_echo_reference(struct mixer *mixer, const char* ec_ref) 254 { 255 struct mixer_ctl *ctl; 256 const char *mixer_ctl_name = "EC_REF_RX"; 257 258 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name); 259 if (!ctl) { 260 ALOGE("%s: Could not get ctl for mixer cmd - %s", 261 __func__, mixer_ctl_name); 262 return -EINVAL; 263 } 264 ALOGV("Setting EC Reference: %s", ec_ref); 265 mixer_ctl_set_enum_by_string(ctl, ec_ref); 266 return 0; 267 } 268 269 void *platform_init(struct audio_device *adev) 270 { 271 char platform[PROPERTY_VALUE_MAX]; 272 char baseband[PROPERTY_VALUE_MAX]; 273 char value[PROPERTY_VALUE_MAX]; 274 struct platform_data *my_data; 275 276 adev->mixer = mixer_open(MIXER_CARD); 277 278 if (!adev->mixer) { 279 ALOGE("Unable to open the mixer, aborting."); 280 return NULL; 281 } 282 283 adev->audio_route = audio_route_init(MIXER_CARD, MIXER_XML_PATH); 284 if (!adev->audio_route) { 285 ALOGE("%s: Failed to init audio route controls, aborting.", __func__); 286 return NULL; 287 } 288 289 my_data = calloc(1, sizeof(struct platform_data)); 290 291 my_data->adev = adev; 292 my_data->dualmic_config = DUALMIC_CONFIG_NONE; 293 my_data->fluence_in_spkr_mode = false; 294 my_data->fluence_in_voice_call = false; 295 my_data->fluence_in_voice_rec = false; 296 297 property_get("persist.audio.dualmic.config",value,""); 298 if (!strcmp("broadside", value)) { 299 my_data->dualmic_config = DUALMIC_CONFIG_BROADSIDE; 300 adev->acdb_settings |= DMIC_FLAG; 301 } else if (!strcmp("endfire", value)) { 302 my_data->dualmic_config = DUALMIC_CONFIG_ENDFIRE; 303 adev->acdb_settings |= DMIC_FLAG; 304 } 305 306 if (my_data->dualmic_config != DUALMIC_CONFIG_NONE) { 307 property_get("persist.audio.fluence.voicecall",value,""); 308 if (!strcmp("true", value)) { 309 my_data->fluence_in_voice_call = true; 310 } 311 312 property_get("persist.audio.fluence.voicerec",value,""); 313 if (!strcmp("true", value)) { 314 my_data->fluence_in_voice_rec = true; 315 } 316 317 property_get("persist.audio.fluence.speaker",value,""); 318 if (!strcmp("true", value)) { 319 my_data->fluence_in_spkr_mode = true; 320 } 321 } 322 323 my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW); 324 if (my_data->acdb_handle == NULL) { 325 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_ACDB_LOADER); 326 } else { 327 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_ACDB_LOADER); 328 my_data->acdb_deallocate = (acdb_deallocate_t)dlsym(my_data->acdb_handle, 329 "acdb_loader_deallocate_ACDB"); 330 my_data->acdb_send_audio_cal = (acdb_send_audio_cal_t)dlsym(my_data->acdb_handle, 331 "acdb_loader_send_audio_cal"); 332 if (!my_data->acdb_send_audio_cal) 333 ALOGW("%s: Could not find the symbol acdb_send_audio_cal from %s", 334 __func__, LIB_ACDB_LOADER); 335 my_data->acdb_send_voice_cal = (acdb_send_voice_cal_t)dlsym(my_data->acdb_handle, 336 "acdb_loader_send_voice_cal"); 337 my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle, 338 "acdb_loader_init_ACDB"); 339 if (my_data->acdb_init == NULL) 340 ALOGE("%s: dlsym error %s for acdb_loader_init_ACDB", __func__, dlerror()); 341 else 342 my_data->acdb_init(); 343 } 344 345 /* If platform is Fusion3, load CSD Client specific symbols 346 * Voice call is handled by MDM and apps processor talks to 347 * MDM through CSD Client 348 */ 349 property_get("ro.board.platform", platform, ""); 350 property_get("ro.baseband", baseband, ""); 351 if (!strcmp("msm8960", platform) && !strcmp("mdm", baseband)) { 352 my_data->csd_client = dlopen(LIB_CSD_CLIENT, RTLD_NOW); 353 if (my_data->csd_client == NULL) 354 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_CSD_CLIENT); 355 } 356 357 if (my_data->csd_client) { 358 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_CSD_CLIENT); 359 my_data->csd_client_deinit = (csd_client_deinit_t)dlsym(my_data->csd_client, 360 "csd_client_deinit"); 361 my_data->csd_disable_device = (csd_disable_device_t)dlsym(my_data->csd_client, 362 "csd_client_disable_device"); 363 my_data->csd_enable_device = (csd_enable_device_t)dlsym(my_data->csd_client, 364 "csd_client_enable_device"); 365 my_data->csd_start_voice = (csd_start_voice_t)dlsym(my_data->csd_client, 366 "csd_client_start_voice"); 367 my_data->csd_stop_voice = (csd_stop_voice_t)dlsym(my_data->csd_client, 368 "csd_client_stop_voice"); 369 my_data->csd_volume = (csd_volume_t)dlsym(my_data->csd_client, 370 "csd_client_volume"); 371 my_data->csd_mic_mute = (csd_mic_mute_t)dlsym(my_data->csd_client, 372 "csd_client_mic_mute"); 373 my_data->csd_client_init = (csd_client_init_t)dlsym(my_data->csd_client, 374 "csd_client_init"); 375 376 if (my_data->csd_client_init == NULL) { 377 ALOGE("%s: dlsym error %s for csd_client_init", __func__, dlerror()); 378 } else { 379 my_data->csd_client_init(); 380 } 381 } 382 383 return my_data; 384 } 385 386 void platform_deinit(void *platform) 387 { 388 free(platform); 389 } 390 391 const char *platform_get_snd_device_name(snd_device_t snd_device) 392 { 393 if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX) 394 return device_table[snd_device]; 395 else 396 return "none"; 397 } 398 399 void platform_add_backend_name(void *platform __unused, char *mixer_path, 400 snd_device_t snd_device) 401 { 402 if (snd_device == SND_DEVICE_IN_BT_SCO_MIC) 403 strcat(mixer_path, " bt-sco"); 404 else if(snd_device == SND_DEVICE_OUT_BT_SCO) 405 strcat(mixer_path, " bt-sco"); 406 else if (snd_device == SND_DEVICE_OUT_HDMI) 407 strcat(mixer_path, " hdmi"); 408 else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HDMI) 409 strcat(mixer_path, " speaker-and-hdmi"); 410 else if (snd_device == SND_DEVICE_OUT_BT_SCO_WB || 411 snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB) 412 strcat(mixer_path, " bt-sco-wb"); 413 } 414 415 int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type) 416 { 417 int device_id; 418 if (device_type == PCM_PLAYBACK) 419 device_id = pcm_device_table[usecase][0]; 420 else 421 device_id = pcm_device_table[usecase][1]; 422 return device_id; 423 } 424 425 int platform_get_snd_device_index(char *snd_device_index_name __unused) 426 { 427 return -ENODEV; 428 } 429 430 int platform_set_snd_device_acdb_id(snd_device_t snd_device __unused, 431 unsigned int acdb_id __unused) 432 { 433 return -ENODEV; 434 } 435 436 int platform_get_default_app_type_v2(void *platform __unused, usecase_type_t type __unused, 437 int *app_type __unused) 438 { 439 ALOGE("%s: Not implemented", __func__); 440 return -ENOSYS; 441 } 442 443 int platform_get_snd_device_acdb_id(snd_device_t snd_device __unused) 444 { 445 ALOGE("%s: Not implemented", __func__); 446 return -ENOSYS; 447 } 448 449 void platform_add_operator_specific_device(snd_device_t snd_device __unused, 450 const char *operator __unused, 451 const char *mixer_path __unused, 452 unsigned int acdb_id __unused) 453 { 454 } 455 456 int platform_send_audio_calibration(void *platform, snd_device_t snd_device) 457 { 458 struct platform_data *my_data = (struct platform_data *)platform; 459 int acdb_dev_id, acdb_dev_type; 460 461 acdb_dev_id = acdb_device_table[snd_device]; 462 if (acdb_dev_id < 0) { 463 ALOGE("%s: Could not find acdb id for device(%d)", 464 __func__, snd_device); 465 return -EINVAL; 466 } 467 if (my_data->acdb_send_audio_cal) { 468 ("%s: sending audio calibration for snd_device(%d) acdb_id(%d)", 469 __func__, snd_device, acdb_dev_id); 470 if (snd_device >= SND_DEVICE_OUT_BEGIN && 471 snd_device < SND_DEVICE_OUT_END) 472 acdb_dev_type = ACDB_DEV_TYPE_OUT; 473 else 474 acdb_dev_type = ACDB_DEV_TYPE_IN; 475 my_data->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type); 476 } 477 return 0; 478 } 479 480 int platform_switch_voice_call_device_pre(void *platform) 481 { 482 struct platform_data *my_data = (struct platform_data *)platform; 483 int ret = 0; 484 485 if (my_data->csd_client != NULL && 486 voice_is_in_call(my_data->adev)) { 487 /* This must be called before disabling the mixer controls on APQ side */ 488 if (my_data->csd_disable_device == NULL) { 489 ALOGE("%s: dlsym error for csd_disable_device", __func__); 490 } else { 491 ret = my_data->csd_disable_device(); 492 if (ret < 0) { 493 ALOGE("%s: csd_client_disable_device, failed, error %d", 494 __func__, ret); 495 } 496 } 497 } 498 return ret; 499 } 500 501 int platform_switch_voice_call_device_post(void *platform, 502 snd_device_t out_snd_device, 503 snd_device_t in_snd_device) 504 { 505 struct platform_data *my_data = (struct platform_data *)platform; 506 int acdb_rx_id, acdb_tx_id; 507 int ret = 0; 508 509 if (my_data->csd_client) { 510 if (my_data->csd_enable_device == NULL) { 511 ALOGE("%s: dlsym error for csd_enable_device", 512 __func__); 513 } else { 514 acdb_rx_id = acdb_device_table[out_snd_device]; 515 acdb_tx_id = acdb_device_table[in_snd_device]; 516 517 if (acdb_rx_id > 0 || acdb_tx_id > 0) { 518 ret = my_data->csd_enable_device(acdb_rx_id, acdb_tx_id, 519 my_data->adev->acdb_settings); 520 if (ret < 0) { 521 ALOGE("%s: csd_enable_device, failed, error %d", 522 __func__, ret); 523 } 524 } else { 525 ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__, 526 acdb_rx_id, acdb_tx_id); 527 } 528 } 529 } 530 531 return ret; 532 } 533 534 int platform_start_voice_call(void *platform, uint32_t vsid __unused) 535 { 536 struct platform_data *my_data = (struct platform_data *)platform; 537 int ret = 0; 538 539 if (my_data->csd_client) { 540 if (my_data->csd_start_voice == NULL) { 541 ALOGE("dlsym error for csd_client_start_voice"); 542 ret = -ENOSYS; 543 } else { 544 ret = my_data->csd_start_voice(); 545 if (ret < 0) { 546 ALOGE("%s: csd_start_voice error %d\n", __func__, ret); 547 } 548 } 549 } 550 551 return ret; 552 } 553 554 int platform_stop_voice_call(void *platform, uint32_t vsid __unused) 555 { 556 struct platform_data *my_data = (struct platform_data *)platform; 557 int ret = 0; 558 559 if (my_data->csd_client) { 560 if (my_data->csd_stop_voice == NULL) { 561 ALOGE("dlsym error for csd_stop_voice"); 562 } else { 563 ret = my_data->csd_stop_voice(); 564 if (ret < 0) { 565 ALOGE("%s: csd_stop_voice error %d\n", __func__, ret); 566 } 567 } 568 } 569 570 return ret; 571 } 572 573 void platform_set_speaker_gain_in_combo(struct audio_device *adev __unused, 574 snd_device_t snd_device __unused, 575 bool enable __unused) { 576 } 577 578 int platform_set_voice_volume(void *platform, int volume) 579 { 580 struct platform_data *my_data = (struct platform_data *)platform; 581 int ret = 0; 582 583 if (my_data->csd_client) { 584 if (my_data->csd_volume == NULL) { 585 ALOGE("%s: dlsym error for csd_volume", __func__); 586 } else { 587 ret = my_data->csd_volume(volume); 588 if (ret < 0) { 589 ALOGE("%s: csd_volume error %d", __func__, ret); 590 } 591 } 592 } else { 593 ALOGE("%s: No CSD Client present", __func__); 594 } 595 596 return ret; 597 } 598 599 int platform_set_mic_mute(void *platform, bool state) 600 { 601 struct platform_data *my_data = (struct platform_data *)platform; 602 int ret = 0; 603 604 if (my_data->adev->mode == AUDIO_MODE_IN_CALL) { 605 if (my_data->csd_client) { 606 if (my_data->csd_mic_mute == NULL) { 607 ALOGE("%s: dlsym error for csd_mic_mute", __func__); 608 } else { 609 ret = my_data->csd_mic_mute(state); 610 if (ret < 0) { 611 ALOGE("%s: csd_mic_mute error %d", __func__, ret); 612 } 613 } 614 } else { 615 ALOGE("%s: No CSD Client present", __func__); 616 } 617 } 618 619 return ret; 620 } 621 622 int platform_set_device_mute(void *platform __unused, bool state __unused, char *dir __unused) 623 { 624 ALOGE("%s: Not implemented", __func__); 625 return -ENOSYS; 626 } 627 628 snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices) 629 { 630 struct platform_data *my_data = (struct platform_data *)platform; 631 struct audio_device *adev = my_data->adev; 632 audio_mode_t mode = adev->mode; 633 snd_device_t snd_device = SND_DEVICE_NONE; 634 635 ALOGV("%s: enter: output devices(%#x)", __func__, devices); 636 if (devices == AUDIO_DEVICE_NONE || 637 devices & AUDIO_DEVICE_BIT_IN) { 638 ALOGV("%s: Invalid output devices (%#x)", __func__, devices); 639 goto exit; 640 } 641 642 if (voice_is_in_call(adev)) { 643 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE || 644 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) { 645 if (adev->voice.tty_mode == TTY_MODE_FULL) 646 snd_device = SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES; 647 else if (adev->voice.tty_mode == TTY_MODE_VCO) 648 snd_device = SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES; 649 else if (adev->voice.tty_mode == TTY_MODE_HCO) 650 snd_device = SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET; 651 else 652 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES; 653 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) { 654 if (adev->bt_wb_speech_enabled) { 655 snd_device = SND_DEVICE_OUT_BT_SCO_WB; 656 } else { 657 snd_device = SND_DEVICE_OUT_BT_SCO; 658 } 659 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) { 660 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER; 661 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) { 662 if (is_operator_tmus()) 663 snd_device = SND_DEVICE_OUT_VOICE_HANDSET_TMUS; 664 else 665 snd_device = SND_DEVICE_OUT_HANDSET; 666 } 667 if (snd_device != SND_DEVICE_NONE) { 668 goto exit; 669 } 670 } 671 672 if (popcount(devices) == 2) { 673 if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE | 674 AUDIO_DEVICE_OUT_SPEAKER)) { 675 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES; 676 } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET | 677 AUDIO_DEVICE_OUT_SPEAKER)) { 678 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES; 679 } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL | 680 AUDIO_DEVICE_OUT_SPEAKER)) { 681 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI; 682 } else { 683 ALOGE("%s: Invalid combo device(%#x)", __func__, devices); 684 goto exit; 685 } 686 if (snd_device != SND_DEVICE_NONE) { 687 goto exit; 688 } 689 } 690 691 if (popcount(devices) != 1) { 692 ALOGE("%s: Invalid output devices(%#x)", __func__, devices); 693 goto exit; 694 } 695 696 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE || 697 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) { 698 snd_device = SND_DEVICE_OUT_HEADPHONES; 699 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) { 700 /* 701 * Perform device switch only if acdb tuning is different between SPEAKER & SPEAKER_REVERSE, 702 * Or there will be a small pause while performing device switch. 703 */ 704 if (my_data->speaker_lr_swap && 705 (acdb_device_table[SND_DEVICE_OUT_SPEAKER] != 706 acdb_device_table[SND_DEVICE_OUT_SPEAKER_REVERSE])) 707 snd_device = SND_DEVICE_OUT_SPEAKER_REVERSE; 708 else 709 snd_device = SND_DEVICE_OUT_SPEAKER; 710 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) { 711 if (adev->bt_wb_speech_enabled) { 712 snd_device = SND_DEVICE_OUT_BT_SCO_WB; 713 } else { 714 snd_device = SND_DEVICE_OUT_BT_SCO; 715 } 716 } else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) { 717 snd_device = SND_DEVICE_OUT_HDMI ; 718 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) { 719 snd_device = SND_DEVICE_OUT_HANDSET; 720 } else { 721 ALOGE("%s: Unknown device(s) %#x", __func__, devices); 722 } 723 exit: 724 ALOGV("%s: exit: snd_device(%s)", __func__, device_table[snd_device]); 725 return snd_device; 726 } 727 728 snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device) 729 { 730 struct platform_data *my_data = (struct platform_data *)platform; 731 struct audio_device *adev = my_data->adev; 732 audio_source_t source = (adev->active_input == NULL) ? 733 AUDIO_SOURCE_DEFAULT : adev->active_input->source; 734 735 audio_mode_t mode = adev->mode; 736 audio_devices_t in_device = ((adev->active_input == NULL) ? 737 AUDIO_DEVICE_NONE : adev->active_input->device) 738 & ~AUDIO_DEVICE_BIT_IN; 739 audio_channel_mask_t channel_mask = (adev->active_input == NULL) ? 740 AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask; 741 snd_device_t snd_device = SND_DEVICE_NONE; 742 743 ALOGV("%s: enter: out_device(%#x) in_device(%#x)", 744 __func__, out_device, in_device); 745 if ((out_device != AUDIO_DEVICE_NONE) && voice_is_in_call(adev)) { 746 if (adev->voice.tty_mode != TTY_MODE_OFF) { 747 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE || 748 out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) { 749 switch (adev->voice.tty_mode) { 750 case TTY_MODE_FULL: 751 snd_device = SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC; 752 break; 753 case TTY_MODE_VCO: 754 snd_device = SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC; 755 break; 756 case TTY_MODE_HCO: 757 snd_device = SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC; 758 break; 759 default: 760 ALOGE("%s: Invalid TTY mode (%#x)", __func__, adev->voice.tty_mode); 761 } 762 goto exit; 763 } 764 } 765 if (out_device & AUDIO_DEVICE_OUT_EARPIECE || 766 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) { 767 if (my_data->fluence_in_voice_call == false) { 768 snd_device = SND_DEVICE_IN_HANDSET_MIC; 769 } else { 770 if (my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) { 771 if (is_operator_tmus()) 772 snd_device = SND_DEVICE_IN_VOICE_DMIC_EF_TMUS; 773 else 774 snd_device = SND_DEVICE_IN_VOICE_DMIC_EF; 775 } else if(my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE) 776 snd_device = SND_DEVICE_IN_VOICE_DMIC_BS; 777 else 778 snd_device = SND_DEVICE_IN_HANDSET_MIC; 779 } 780 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) { 781 snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC; 782 } else if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) { 783 if (adev->bt_wb_speech_enabled) { 784 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB; 785 } else { 786 snd_device = SND_DEVICE_IN_BT_SCO_MIC; 787 } 788 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) { 789 if (my_data->fluence_in_voice_call && my_data->fluence_in_spkr_mode && 790 my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) { 791 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF; 792 } else if (my_data->fluence_in_voice_call && my_data->fluence_in_spkr_mode && 793 my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE) { 794 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS; 795 } else { 796 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC; 797 } 798 } 799 } else if (source == AUDIO_SOURCE_CAMCORDER) { 800 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC || 801 in_device & AUDIO_DEVICE_IN_BACK_MIC) { 802 snd_device = SND_DEVICE_IN_CAMCORDER_MIC; 803 } 804 } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) { 805 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) { 806 if (my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) { 807 if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK) 808 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_EF; 809 else if (my_data->fluence_in_voice_rec) 810 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE; 811 } else if (my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE) { 812 if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK) 813 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_BS; 814 else if (my_data->fluence_in_voice_rec) 815 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE; 816 } 817 818 if (snd_device == SND_DEVICE_NONE) { 819 snd_device = SND_DEVICE_IN_VOICE_REC_MIC; 820 } 821 } 822 } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION || 823 mode == AUDIO_MODE_IN_COMMUNICATION) { 824 if (out_device & AUDIO_DEVICE_OUT_SPEAKER) 825 in_device = AUDIO_DEVICE_IN_BACK_MIC; 826 if (adev->active_input) { 827 if (adev->active_input->enable_aec) { 828 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) { 829 snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC; 830 } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) { 831 snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC; 832 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) { 833 snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC; 834 } 835 set_echo_reference(adev->mixer, "SLIM_RX"); 836 } else 837 set_echo_reference(adev->mixer, "NONE"); 838 } 839 } else if (source == AUDIO_SOURCE_DEFAULT) { 840 goto exit; 841 } 842 843 844 if (snd_device != SND_DEVICE_NONE) { 845 goto exit; 846 } 847 848 if (in_device != AUDIO_DEVICE_NONE && 849 !(in_device & AUDIO_DEVICE_IN_VOICE_CALL) && 850 !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) { 851 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) { 852 snd_device = SND_DEVICE_IN_HANDSET_MIC; 853 } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) { 854 snd_device = SND_DEVICE_IN_SPEAKER_MIC; 855 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) { 856 snd_device = SND_DEVICE_IN_HEADSET_MIC; 857 } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) { 858 if (adev->bt_wb_speech_enabled) { 859 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB; 860 } else { 861 snd_device = SND_DEVICE_IN_BT_SCO_MIC; 862 } 863 } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) { 864 snd_device = SND_DEVICE_IN_HDMI_MIC; 865 } else { 866 ALOGE("%s: Unknown input device(s) %#x", __func__, in_device); 867 ALOGW("%s: Using default handset-mic", __func__); 868 snd_device = SND_DEVICE_IN_HANDSET_MIC; 869 } 870 } else { 871 if (out_device & AUDIO_DEVICE_OUT_EARPIECE) { 872 snd_device = SND_DEVICE_IN_HANDSET_MIC; 873 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) { 874 snd_device = SND_DEVICE_IN_HEADSET_MIC; 875 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) { 876 snd_device = SND_DEVICE_IN_SPEAKER_MIC; 877 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) { 878 snd_device = SND_DEVICE_IN_HANDSET_MIC; 879 } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) { 880 if (adev->bt_wb_speech_enabled) { 881 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB; 882 } else { 883 snd_device = SND_DEVICE_IN_BT_SCO_MIC; 884 } 885 } else if (out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL) { 886 snd_device = SND_DEVICE_IN_HDMI_MIC; 887 } else { 888 ALOGE("%s: Unknown output device(s) %#x", __func__, out_device); 889 ALOGW("%s: Using default handset-mic", __func__); 890 snd_device = SND_DEVICE_IN_HANDSET_MIC; 891 } 892 } 893 exit: 894 ALOGV("%s: exit: in_snd_device(%s)", __func__, device_table[snd_device]); 895 return snd_device; 896 } 897 898 int platform_set_hdmi_channels(void *platform, int channel_count) 899 { 900 struct platform_data *my_data = (struct platform_data *)platform; 901 struct audio_device *adev = my_data->adev; 902 struct mixer_ctl *ctl; 903 const char *channel_cnt_str = NULL; 904 const char *mixer_ctl_name = "HDMI_RX Channels"; 905 switch (channel_count) { 906 case 8: 907 channel_cnt_str = "Eight"; break; 908 case 7: 909 channel_cnt_str = "Seven"; break; 910 case 6: 911 channel_cnt_str = "Six"; break; 912 case 5: 913 channel_cnt_str = "Five"; break; 914 case 4: 915 channel_cnt_str = "Four"; break; 916 case 3: 917 channel_cnt_str = "Three"; break; 918 default: 919 channel_cnt_str = "Two"; break; 920 } 921 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name); 922 if (!ctl) { 923 ALOGE("%s: Could not get ctl for mixer cmd - %s", 924 __func__, mixer_ctl_name); 925 return -EINVAL; 926 } 927 ALOGV("HDMI channel count: %s", channel_cnt_str); 928 mixer_ctl_set_enum_by_string(ctl, channel_cnt_str); 929 return 0; 930 } 931 932 int platform_edid_get_max_channels(void *platform __unused) 933 { 934 FILE *file; 935 struct audio_block_header header; 936 char block[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE]; 937 char *sad = block; 938 int num_audio_blocks; 939 int channel_count; 940 int max_channels = 0; 941 int i; 942 943 file = fopen(AUDIO_DATA_BLOCK_PATH, "rb"); 944 if (file == NULL) { 945 ALOGE("Unable to open '%s'", AUDIO_DATA_BLOCK_PATH); 946 return 0; 947 } 948 949 /* Read audio block header */ 950 fread(&header, 1, sizeof(header), file); 951 952 /* Read SAD blocks, clamping the maximum size for safety */ 953 if (header.length > (int)sizeof(block)) 954 header.length = (int)sizeof(block); 955 fread(&block, header.length, 1, file); 956 957 fclose(file); 958 959 /* Calculate the number of SAD blocks */ 960 num_audio_blocks = header.length / SAD_BLOCK_SIZE; 961 962 for (i = 0; i < num_audio_blocks; i++) { 963 /* Only consider LPCM blocks */ 964 if ((sad[0] >> 3) != EDID_FORMAT_LPCM) 965 continue; 966 967 channel_count = (sad[0] & 0x7) + 1; 968 if (channel_count > max_channels) 969 max_channels = channel_count; 970 971 /* Advance to next block */ 972 sad += 3; 973 } 974 975 return max_channels; 976 } 977 978 int platform_set_incall_recording_session_id(void *platform __unused, 979 uint32_t session_id __unused, int rec_mode __unused) 980 { 981 ALOGE("%s: Not implemented", __func__); 982 return -ENOSYS; 983 } 984 985 int platform_stop_incall_recording_usecase(void *platform __unused) 986 { 987 ALOGE("%s: Not implemented", __func__); 988 return -ENOSYS; 989 } 990 991 int platform_start_incall_music_usecase(void *platform __unused) 992 { 993 ALOGE("%s: Not implemented", __func__); 994 return -ENOSYS; 995 } 996 997 int platform_stop_incall_music_usecase(void *platform __unused) 998 { 999 ALOGE("%s: Not implemented", __func__); 1000 return -ENOSYS; 1001 } 1002 1003 int platform_set_parameters(void *platform __unused, 1004 struct str_parms *parms __unused) 1005 { 1006 ALOGE("%s: Not implemented", __func__); 1007 return -ENOSYS; 1008 } 1009 1010 /* Delay in Us */ 1011 int64_t platform_render_latency(audio_usecase_t usecase) 1012 { 1013 switch (usecase) { 1014 case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER: 1015 return DEEP_BUFFER_PLATFORM_DELAY; 1016 case USECASE_AUDIO_PLAYBACK_LOW_LATENCY: 1017 return LOW_LATENCY_PLATFORM_DELAY; 1018 default: 1019 return 0; 1020 } 1021 } 1022 1023 int platform_switch_voice_call_enable_device_config(void *platform __unused, 1024 snd_device_t out_snd_device __unused, 1025 snd_device_t in_snd_device __unused) 1026 { 1027 return 0; 1028 } 1029 1030 int platform_switch_voice_call_usecase_route_post(void *platform __unused, 1031 snd_device_t out_snd_device __unused, 1032 snd_device_t in_snd_device __unused) 1033 { 1034 return 0; 1035 } 1036 1037 int platform_get_sample_rate(void *platform __unused, uint32_t *rate __unused) 1038 { 1039 return -ENOSYS; 1040 } 1041 1042 int platform_get_usecase_index(const char * usecase __unused) 1043 { 1044 return -ENOSYS; 1045 } 1046 1047 int platform_set_usecase_pcm_id(audio_usecase_t usecase __unused, int32_t type __unused, 1048 int32_t pcm_id __unused) 1049 { 1050 return -ENOSYS; 1051 } 1052 1053 int platform_set_snd_device_backend(snd_device_t device __unused, 1054 const char *backend __unused, 1055 const char *hw_interface __unused) 1056 { 1057 return -ENOSYS; 1058 } 1059 1060 void platform_set_echo_reference(struct audio_device *adev __unused, 1061 bool enable __unused, 1062 audio_devices_t out_device __unused) 1063 { 1064 return; 1065 } 1066 1067 #define DEFAULT_NOMINAL_SPEAKER_GAIN 20 1068 int ramp_speaker_gain(struct audio_device *adev, bool ramp_up, int target_ramp_up_gain) { 1069 // backup_gain: gain to try to set in case of an error during ramp 1070 int start_gain, end_gain, step, backup_gain, i; 1071 bool error = false; 1072 const struct mixer_ctl *ctl; 1073 const char *mixer_ctl_name_gain_left = "Left Speaker Gain"; 1074 const char *mixer_ctl_name_gain_right = "Right Speaker Gain"; 1075 struct mixer_ctl *ctl_left = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name_gain_left); 1076 struct mixer_ctl *ctl_right = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name_gain_right); 1077 if (!ctl_left || !ctl_right) { 1078 ALOGE("%s: Could not get ctl for mixer cmd - %s or %s, not applying speaker gain ramp", 1079 __func__, mixer_ctl_name_gain_left, mixer_ctl_name_gain_right); 1080 return -EINVAL; 1081 } else if ((mixer_ctl_get_num_values(ctl_left) != 1) 1082 || (mixer_ctl_get_num_values(ctl_right) != 1)) { 1083 ALOGE("%s: Unexpected num values for mixer cmd - %s or %s, not applying speaker gain ramp", 1084 __func__, mixer_ctl_name_gain_left, mixer_ctl_name_gain_right); 1085 return -EINVAL; 1086 } 1087 if (ramp_up) { 1088 start_gain = 0; 1089 end_gain = target_ramp_up_gain > 0 ? target_ramp_up_gain : DEFAULT_NOMINAL_SPEAKER_GAIN; 1090 step = +1; 1091 backup_gain = end_gain; 1092 } else { 1093 // using same gain on left and right 1094 const int left_gain = mixer_ctl_get_value(ctl_left, 0); 1095 start_gain = left_gain > 0 ? left_gain : DEFAULT_NOMINAL_SPEAKER_GAIN; 1096 end_gain = 0; 1097 step = -1; 1098 backup_gain = start_gain; 1099 } 1100 for (i = start_gain ; i != (end_gain + step) ; i += step) { 1101 //ALOGV("setting speaker gain to %d", i); 1102 if (mixer_ctl_set_value(ctl_left, 0, i)) { 1103 ALOGE("%s: error setting %s to %d during gain ramp", 1104 __func__, mixer_ctl_name_gain_left, i); 1105 error = true; 1106 break; 1107 } 1108 if (mixer_ctl_set_value(ctl_right, 0, i)) { 1109 ALOGE("%s: error setting %s to %d during gain ramp", 1110 __func__, mixer_ctl_name_gain_right, i); 1111 error = true; 1112 break; 1113 } 1114 usleep(1000); 1115 } 1116 if (error) { 1117 // an error occured during the ramp, let's still try to go back to a safe volume 1118 if (mixer_ctl_set_value(ctl_left, 0, backup_gain)) { 1119 ALOGE("%s: error restoring left gain to %d", __func__, backup_gain); 1120 } 1121 if (mixer_ctl_set_value(ctl_right, 0, backup_gain)) { 1122 ALOGE("%s: error restoring right gain to %d", __func__, backup_gain); 1123 } 1124 } 1125 return start_gain; 1126 } 1127 1128 int platform_set_swap_mixer(struct audio_device *adev, bool swap_channels) 1129 { 1130 const char *mixer_ctl_name = "Swap channel"; 1131 struct mixer_ctl *ctl; 1132 const char *mixer_path; 1133 struct platform_data *my_data = (struct platform_data *)adev->platform; 1134 1135 // forced to set to swap, but device not rotated ... ignore set 1136 if (swap_channels && !my_data->speaker_lr_swap) 1137 return 0; 1138 1139 ALOGV("%s:", __func__); 1140 1141 if (swap_channels) { 1142 mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER_REVERSE); 1143 audio_route_apply_and_update_path(adev->audio_route, mixer_path); 1144 } else { 1145 mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER); 1146 audio_route_apply_and_update_path(adev->audio_route, mixer_path); 1147 } 1148 1149 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name); 1150 if (!ctl) { 1151 ALOGE("%s: Could not get ctl for mixer cmd - %s",__func__, mixer_ctl_name); 1152 return -EINVAL; 1153 } 1154 1155 if (mixer_ctl_set_value(ctl, 0, swap_channels) < 0) { 1156 ALOGE("%s: Could not set reverse cotrol %d",__func__, swap_channels); 1157 return -EINVAL; 1158 } 1159 1160 ALOGV("platfor_force_swap_channel :: Channel orientation ( %s ) ", 1161 swap_channels?"R --> L":"L --> R"); 1162 1163 return 0; 1164 } 1165 1166 int platform_check_and_set_swap_lr_channels(struct audio_device *adev, bool swap_channels) 1167 { 1168 // only update if there is active pcm playback on speaker 1169 struct audio_usecase *usecase; 1170 struct listnode *node; 1171 struct platform_data *my_data = (struct platform_data *)adev->platform; 1172 1173 my_data->speaker_lr_swap = swap_channels; 1174 1175 return platform_set_swap_channels(adev, swap_channels); 1176 } 1177 1178 int platform_set_swap_channels(struct audio_device *adev, bool swap_channels) 1179 { 1180 // only update if there is active pcm playback on speaker 1181 struct audio_usecase *usecase; 1182 struct listnode *node; 1183 struct platform_data *my_data = (struct platform_data *)adev->platform; 1184 1185 // do not swap channels in audio modes with concurrent capture and playback 1186 // as this may break the echo reference 1187 if ((adev->mode == AUDIO_MODE_IN_COMMUNICATION) || (adev->mode == AUDIO_MODE_IN_CALL)) { 1188 ALOGV("%s: will not swap due to audio mode %d", __func__, adev->mode); 1189 return 0; 1190 } 1191 1192 list_for_each(node, &adev->usecase_list) { 1193 usecase = node_to_item(node, struct audio_usecase, list); 1194 if (usecase->type == PCM_PLAYBACK && 1195 usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER) { 1196 /* 1197 * If acdb tuning is different for SPEAKER_REVERSE, it is must 1198 * to perform device switch to disable the current backend to 1199 * enable it with new acdb data. 1200 */ 1201 if (acdb_device_table[SND_DEVICE_OUT_SPEAKER] != 1202 acdb_device_table[SND_DEVICE_OUT_SPEAKER_REVERSE]) { 1203 const int initial_skpr_gain = ramp_speaker_gain(adev, false /*ramp_up*/, -1); 1204 select_devices(adev, usecase->id); 1205 if (initial_skpr_gain != -EINVAL) 1206 ramp_speaker_gain(adev, true /*ramp_up*/, initial_skpr_gain); 1207 1208 } else { 1209 platform_set_swap_mixer(adev, swap_channels); 1210 } 1211 break; 1212 } 1213 } 1214 1215 return 0; 1216 } 1217 1218 bool platform_send_gain_dep_cal(void *platform __unused, 1219 int level __unused) 1220 { 1221 return true; 1222 } 1223 1224 int platform_can_split_snd_device(snd_device_t in_snd_device __unused, 1225 int *num_devices __unused, 1226 snd_device_t *out_snd_devices __unused) 1227 { 1228 return -ENOSYS; 1229 } 1230 1231 bool platform_check_backends_match(snd_device_t snd_device1 __unused, 1232 snd_device_t snd_device2 __unused) 1233 { 1234 return true; 1235 } 1236 1237 int platform_get_snd_device_name_extn(void *platform __unused, 1238 snd_device_t snd_device, 1239 char *device_name) 1240 { 1241 strlcpy(device_name, platform_get_snd_device_name(snd_device), 1242 DEVICE_NAME_MAX_SIZE); 1243 return 0; 1244 } 1245 1246 bool platform_check_and_set_playback_backend_cfg(struct audio_device* adev __unused, 1247 struct audio_usecase *usecase __unused, 1248 snd_device_t snd_device __unused) 1249 { 1250 return false; 1251 } 1252 1253 bool platform_check_and_set_capture_backend_cfg(struct audio_device* adev __unused, 1254 struct audio_usecase *usecase __unused, snd_device_t snd_device __unused) 1255 { 1256 return false; 1257 } 1258 1259 bool platform_add_gain_level_mapping(struct amp_db_and_gain_table *tbl_entry __unused) 1260 { 1261 return false; 1262 } 1263 1264 int platform_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl __unused, 1265 int table_size __unused) 1266 { 1267 return 0; 1268 } 1269 1270 int platform_snd_card_update(void *platform __unused, 1271 card_status_t status __unused) 1272 { 1273 return -1; 1274 } 1275 1276 int platform_get_snd_device_backend_index(snd_device_t snd_device __unused) 1277 { 1278 return -ENOSYS; 1279 } 1280 1281 void platform_check_and_update_copp_sample_rate(void* platform __unused, snd_device_t snd_device __unused, 1282 unsigned int stream_sr __unused, int* sample_rate __unused) 1283 { 1284 1285 } 1286 1287 int platform_send_audio_calibration_v2(void *platform __unused, struct audio_usecase *usecase __unused, 1288 int app_type __unused, int sample_rate __unused) 1289 { 1290 return -ENOSYS; 1291 } 1292 1293 bool platform_supports_app_type_cfg() { return false; } 1294 1295 void platform_add_app_type(const char *uc_type __unused, 1296 const char *mode __unused, 1297 int bw __unused, int app_type __unused, 1298 int max_sr __unused) {} 1299 1300 int platform_get_app_type_v2(void *platform __unused, 1301 enum usecase_type_t type __unused, 1302 const char *mode __unused, 1303 int bw __unused, int sr __unused, 1304 int *app_type __unused) { 1305 return -ENOSYS; 1306 } 1307 1308 int platform_set_sidetone(struct audio_device *adev, 1309 snd_device_t out_snd_device, 1310 bool enable, char *str) 1311 { 1312 int ret; 1313 if (out_snd_device == SND_DEVICE_OUT_USB_HEADSET || 1314 out_snd_device == SND_DEVICE_OUT_VOICE_USB_HEADSET) { 1315 ret = audio_extn_usb_enable_sidetone(out_snd_device, enable); 1316 if (ret) 1317 ALOGI("%s: usb device %d does not support device sidetone\n", 1318 __func__, out_snd_device); 1319 } else { 1320 ALOGV("%s: sidetone out device(%d) mixer cmd = %s\n", 1321 __func__, out_snd_device, str); 1322 if (enable) 1323 audio_route_apply_and_update_path(adev->audio_route, str); 1324 else 1325 audio_route_reset_and_update_path(adev->audio_route, str); 1326 } 1327 return 0; 1328 } 1329 1330 int platform_get_mmap_data_fd(void *platform __unused, int fe_dev __unused, int dir __unused, 1331 int *fd __unused, uint32_t *size __unused) 1332 { 1333 return -ENOSYS; 1334 } 1335 1336 bool platform_sound_trigger_usecase_needs_event(audio_usecase_t uc_id __unused) 1337 { 1338 return false; 1339 } 1340 1341 bool platform_snd_device_has_speaker(snd_device_t dev __unused) { 1342 return false; 1343 } 1344 1345 bool platform_set_microphone_characteristic(void *platform __unused, 1346 struct audio_microphone_characteristic_t mic __unused) { 1347 return -ENOSYS; 1348 } 1349 1350 int platform_get_microphones(void *platform __unused, 1351 struct audio_microphone_characteristic_t *mic_array __unused, 1352 size_t *mic_count __unused) { 1353 return -ENOSYS; 1354 } 1355 1356 int platform_get_active_microphones(void *platform __unused, unsigned int channels __unused, 1357 audio_usecase_t usecase __unused, 1358 struct audio_microphone_characteristic_t *mic_array __unused, 1359 size_t *mic_count __unused) { 1360 return -ENOSYS; 1361 } 1362 1363 int platform_set_usb_service_interval(void *platform __unused, 1364 bool playback __unused, 1365 unsigned long service_interval __unused, 1366 bool *reconfig) 1367 { 1368 *reconfig = false; 1369 return 0; 1370 } 1371 1372 int platform_set_backend_cfg(const struct audio_device* adev __unused, 1373 snd_device_t snd_device __unused, 1374 const struct audio_backend_cfg *backend_cfg __unused) 1375 { 1376 return -1; 1377 } 1378 1379 int platform_set_acdb_metainfo_key(void *platform __unused, 1380 char *name __unused, 1381 int key __unused) { 1382 return -ENOSYS; 1383 } 1384