platform.c revision 3ad4e1b9949d04ad90d053458b10fa4dfbfa088e
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 "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#define MAX_SND_CARD 8 55 56struct audio_block_header 57{ 58 int reserved; 59 int length; 60}; 61 62/* Audio calibration related functions */ 63typedef void (*acdb_deallocate_t)(); 64#ifdef PLATFORM_MSM8084 65typedef int (*acdb_init_t)(char *); 66#else 67typedef int (*acdb_init_t)(); 68#endif 69typedef void (*acdb_send_audio_cal_t)(int, int); 70typedef void (*acdb_send_voice_cal_t)(int, int); 71typedef int (*acdb_reload_vocvoltable_t)(int); 72 73/* Audio calibration related functions */ 74struct platform_data { 75 struct audio_device *adev; 76 bool fluence_in_spkr_mode; 77 bool fluence_in_voice_call; 78 bool fluence_in_voice_comm; 79 bool fluence_in_voice_rec; 80 int dualmic_config; 81 void *acdb_handle; 82 acdb_init_t acdb_init; 83 acdb_deallocate_t acdb_deallocate; 84 acdb_send_audio_cal_t acdb_send_audio_cal; 85 acdb_send_voice_cal_t acdb_send_voice_cal; 86 acdb_reload_vocvoltable_t acdb_reload_vocvoltable; 87 struct csd_data *csd; 88 bool ext_speaker; 89 bool ext_earpiece; 90}; 91 92static int pcm_device_table[AUDIO_USECASE_MAX][2] = { 93 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {DEEP_BUFFER_PCM_DEVICE, 94 DEEP_BUFFER_PCM_DEVICE}, 95 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE, 96 LOWLATENCY_PCM_DEVICE}, 97 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {MULTIMEDIA2_PCM_DEVICE, 98 MULTIMEDIA2_PCM_DEVICE}, 99 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {PLAYBACK_OFFLOAD_DEVICE, 100 PLAYBACK_OFFLOAD_DEVICE}, 101 [USECASE_AUDIO_RECORD] = {AUDIO_RECORD_PCM_DEVICE, 102 AUDIO_RECORD_PCM_DEVICE}, 103 [USECASE_AUDIO_RECORD_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE, 104 LOWLATENCY_PCM_DEVICE}, 105 [USECASE_VOICE_CALL] = {VOICE_CALL_PCM_DEVICE, 106 VOICE_CALL_PCM_DEVICE}, 107 [USECASE_VOICE2_CALL] = {VOICE2_CALL_PCM_DEVICE, VOICE2_CALL_PCM_DEVICE}, 108 [USECASE_VOLTE_CALL] = {VOLTE_CALL_PCM_DEVICE, VOLTE_CALL_PCM_DEVICE}, 109 [USECASE_QCHAT_CALL] = {QCHAT_CALL_PCM_DEVICE, QCHAT_CALL_PCM_DEVICE}, 110 [USECASE_VOWLAN_CALL] = {VOWLAN_CALL_PCM_DEVICE, VOWLAN_CALL_PCM_DEVICE}, 111 [USECASE_INCALL_REC_UPLINK] = {AUDIO_RECORD_PCM_DEVICE, 112 AUDIO_RECORD_PCM_DEVICE}, 113 [USECASE_INCALL_REC_DOWNLINK] = {AUDIO_RECORD_PCM_DEVICE, 114 AUDIO_RECORD_PCM_DEVICE}, 115 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = {AUDIO_RECORD_PCM_DEVICE, 116 AUDIO_RECORD_PCM_DEVICE}, 117 [USECASE_AUDIO_HFP_SCO] = {HFP_PCM_RX, HFP_SCO_RX}, 118}; 119 120/* Array to store sound devices */ 121static const char * const device_table[SND_DEVICE_MAX] = { 122 [SND_DEVICE_NONE] = "none", 123 /* Playback sound devices */ 124 [SND_DEVICE_OUT_HANDSET] = "handset", 125 [SND_DEVICE_OUT_SPEAKER] = "speaker", 126 [SND_DEVICE_OUT_SPEAKER_REVERSE] = "speaker-reverse", 127 [SND_DEVICE_OUT_HEADPHONES] = "headphones", 128 [SND_DEVICE_OUT_LINE] = "line", 129 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones", 130 [SND_DEVICE_OUT_VOICE_HANDSET] = "voice-handset", 131 [SND_DEVICE_OUT_VOICE_HAC_HANDSET] = "voice-hac-handset", 132 [SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker", 133 [SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones", 134 [SND_DEVICE_OUT_VOICE_LINE] = "voice-line", 135 [SND_DEVICE_OUT_HDMI] = "hdmi", 136 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi", 137 [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset", 138 [SND_DEVICE_OUT_BT_SCO_WB] = "bt-sco-headset-wb", 139 [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = "voice-handset-tmus", 140 [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = "voice-tty-full-headphones", 141 [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = "voice-tty-vco-headphones", 142 [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = "voice-tty-hco-handset", 143 144 /* Capture sound devices */ 145 [SND_DEVICE_IN_HANDSET_MIC] = "handset-mic", 146 [SND_DEVICE_IN_HANDSET_MIC_AEC] = "handset-mic", 147 [SND_DEVICE_IN_HANDSET_MIC_NS] = "handset-mic", 148 [SND_DEVICE_IN_HANDSET_MIC_AEC_NS] = "handset-mic", 149 [SND_DEVICE_IN_HANDSET_DMIC] = "dmic-endfire", 150 [SND_DEVICE_IN_HANDSET_DMIC_AEC] = "dmic-endfire", 151 [SND_DEVICE_IN_HANDSET_DMIC_NS] = "dmic-endfire", 152 [SND_DEVICE_IN_HANDSET_DMIC_AEC_NS] = "dmic-endfire", 153 [SND_DEVICE_IN_HANDSET_DMIC_STEREO] = "dmic-endfire", 154 155 [SND_DEVICE_IN_SPEAKER_MIC] = "speaker-mic", 156 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = "speaker-mic", 157 [SND_DEVICE_IN_SPEAKER_MIC_NS] = "speaker-mic", 158 [SND_DEVICE_IN_SPEAKER_MIC_AEC_NS] = "speaker-mic", 159 [SND_DEVICE_IN_SPEAKER_DMIC] = "speaker-dmic-endfire", 160 [SND_DEVICE_IN_SPEAKER_DMIC_AEC] = "speaker-dmic-endfire", 161 [SND_DEVICE_IN_SPEAKER_DMIC_NS] = "speaker-dmic-endfire", 162 [SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS] = "speaker-dmic-endfire", 163 [SND_DEVICE_IN_SPEAKER_DMIC_STEREO] = "speaker-dmic-endfire", 164 165 [SND_DEVICE_IN_HEADSET_MIC] = "headset-mic", 166 167 [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic", 168 [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic", 169 [SND_DEVICE_IN_BT_SCO_MIC_WB] = "bt-sco-mic-wb", 170 171 [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic", 172 173 [SND_DEVICE_IN_VOICE_DMIC] = "voice-dmic-ef", 174 [SND_DEVICE_IN_VOICE_DMIC_TMUS] = "voice-dmic-ef-tmus", 175 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "voice-speaker-mic", 176 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC] = "voice-speaker-dmic-ef", 177 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "voice-headset-mic", 178 [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = "voice-tty-full-headset-mic", 179 [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = "voice-tty-vco-handset-mic", 180 [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = "voice-tty-hco-headset-mic", 181 182 [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic", 183 [SND_DEVICE_IN_VOICE_REC_MIC_NS] = "voice-rec-mic", 184 [SND_DEVICE_IN_VOICE_REC_DMIC_STEREO] = "voice-rec-dmic-ef", 185 [SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE] = "voice-rec-dmic-ef-fluence", 186}; 187 188/* ACDB IDs (audio DSP path configuration IDs) for each sound device */ 189static int acdb_device_table[SND_DEVICE_MAX] = { 190 [SND_DEVICE_NONE] = -1, 191 [SND_DEVICE_OUT_HANDSET] = 7, 192 [SND_DEVICE_OUT_SPEAKER] = 15, 193 [SND_DEVICE_OUT_SPEAKER_REVERSE] = 15, 194 [SND_DEVICE_OUT_HEADPHONES] = 10, 195 [SND_DEVICE_OUT_LINE] = 10, 196 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = 10, 197 [SND_DEVICE_OUT_VOICE_HANDSET] = ACDB_ID_VOICE_HANDSET, 198 [SND_DEVICE_OUT_VOICE_SPEAKER] = ACDB_ID_VOICE_SPEAKER, 199 [SND_DEVICE_OUT_VOICE_HAC_HANDSET] = 53, 200 [SND_DEVICE_OUT_VOICE_HEADPHONES] = 10, 201 [SND_DEVICE_OUT_VOICE_LINE] = 10, 202 [SND_DEVICE_OUT_HDMI] = 18, 203 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 15, 204 [SND_DEVICE_OUT_BT_SCO] = 22, 205 [SND_DEVICE_OUT_BT_SCO_WB] = 39, 206 [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = ACDB_ID_VOICE_HANDSET_TMUS, 207 [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = 17, 208 [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = 17, 209 [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = 37, 210 211 [SND_DEVICE_IN_HANDSET_MIC] = 4, 212 [SND_DEVICE_IN_HANDSET_MIC_AEC] = 106, 213 [SND_DEVICE_IN_HANDSET_MIC_NS] = 107, 214 [SND_DEVICE_IN_HANDSET_MIC_AEC_NS] = 108, 215 [SND_DEVICE_IN_HANDSET_DMIC] = 41, 216 [SND_DEVICE_IN_HANDSET_DMIC_AEC] = 109, 217 [SND_DEVICE_IN_HANDSET_DMIC_NS] = 110, 218 [SND_DEVICE_IN_HANDSET_DMIC_AEC_NS] = 111, 219 [SND_DEVICE_IN_HANDSET_DMIC_STEREO] = 34, 220 221 [SND_DEVICE_IN_SPEAKER_MIC] = 11, 222 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = 112, 223 [SND_DEVICE_IN_SPEAKER_MIC_NS] = 113, 224 [SND_DEVICE_IN_SPEAKER_MIC_AEC_NS] = 114, 225 [SND_DEVICE_IN_SPEAKER_DMIC] = 43, 226 [SND_DEVICE_IN_SPEAKER_DMIC_AEC] = 115, 227 [SND_DEVICE_IN_SPEAKER_DMIC_NS] = 116, 228 [SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS] = 117, 229 [SND_DEVICE_IN_SPEAKER_DMIC_STEREO] = 35, 230 231 [SND_DEVICE_IN_HEADSET_MIC] = 8, 232 233 [SND_DEVICE_IN_HDMI_MIC] = 4, 234 [SND_DEVICE_IN_BT_SCO_MIC] = 21, 235 [SND_DEVICE_IN_BT_SCO_MIC_WB] = 38, 236 237 [SND_DEVICE_IN_CAMCORDER_MIC] = 61, 238 239 [SND_DEVICE_IN_VOICE_DMIC] = 41, 240 [SND_DEVICE_IN_VOICE_DMIC_TMUS] = ACDB_ID_VOICE_DMIC_EF_TMUS, 241 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = 11, 242 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC] = 43, 243 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = 8, 244 [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = 16, 245 [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = 36, 246 [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = 16, 247 248 [SND_DEVICE_IN_VOICE_REC_MIC] = 62, 249 [SND_DEVICE_IN_VOICE_REC_MIC_NS] = 113, 250 [SND_DEVICE_IN_VOICE_REC_DMIC_STEREO] = 35, 251 [SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE] = 43, 252}; 253 254struct name_to_index { 255 char name[100]; 256 unsigned int index; 257}; 258 259#define TO_NAME_INDEX(X) #X, X 260 261/* Used to get index from parsed string */ 262static const struct name_to_index snd_device_name_index[SND_DEVICE_MAX] = { 263 /* out */ 264 {TO_NAME_INDEX(SND_DEVICE_OUT_HANDSET)}, 265 {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER)}, 266 {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_REVERSE)}, 267 {TO_NAME_INDEX(SND_DEVICE_OUT_HEADPHONES)}, 268 {TO_NAME_INDEX(SND_DEVICE_OUT_LINE)}, 269 {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES)}, 270 {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HANDSET)}, 271 {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER)}, 272 {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HEADPHONES)}, 273 {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_LINE)}, 274 {TO_NAME_INDEX(SND_DEVICE_OUT_HDMI)}, 275 {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_HDMI)}, 276 {TO_NAME_INDEX(SND_DEVICE_OUT_BT_SCO)}, 277 {TO_NAME_INDEX(SND_DEVICE_OUT_BT_SCO_WB)}, 278 {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HANDSET_TMUS)}, 279 {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HAC_HANDSET)}, 280 {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES)}, 281 {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES)}, 282 {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET)}, 283 284 /* in */ 285 {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC)}, 286 {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC_AEC)}, 287 {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC_NS)}, 288 {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC_AEC_NS)}, 289 {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_DMIC)}, 290 {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_DMIC_AEC)}, 291 {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_DMIC_NS)}, 292 {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_DMIC_AEC_NS)}, 293 {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_DMIC_STEREO)}, 294 295 {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_MIC)}, 296 {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_MIC_AEC)}, 297 {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_MIC_NS)}, 298 {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_MIC_AEC_NS)}, 299 {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_DMIC)}, 300 {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC)}, 301 {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_NS)}, 302 {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS)}, 303 {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_STEREO)}, 304 305 {TO_NAME_INDEX(SND_DEVICE_IN_HEADSET_MIC)}, 306 307 {TO_NAME_INDEX(SND_DEVICE_IN_HDMI_MIC)}, 308 {TO_NAME_INDEX(SND_DEVICE_IN_BT_SCO_MIC)}, 309 {TO_NAME_INDEX(SND_DEVICE_IN_BT_SCO_MIC_WB)}, 310 311 {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_MIC)}, 312 313 {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_DMIC)}, 314 {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_DMIC_TMUS)}, 315 {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_SPEAKER_MIC)}, 316 {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_SPEAKER_DMIC)}, 317 {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_HEADSET_MIC)}, 318 {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC)}, 319 {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC)}, 320 {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC)}, 321 322 {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_REC_MIC)}, 323 {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_REC_MIC_NS)}, 324 {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_REC_DMIC_STEREO)}, 325 {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE)}, 326}; 327 328static char * backend_table[SND_DEVICE_MAX] = {0}; 329 330static const struct name_to_index usecase_name_index[AUDIO_USECASE_MAX] = { 331 {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_DEEP_BUFFER)}, 332 {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_LOW_LATENCY)}, 333 {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_MULTI_CH)}, 334 {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD)}, 335 {TO_NAME_INDEX(USECASE_AUDIO_RECORD)}, 336 {TO_NAME_INDEX(USECASE_AUDIO_RECORD_LOW_LATENCY)}, 337 {TO_NAME_INDEX(USECASE_VOICE_CALL)}, 338 {TO_NAME_INDEX(USECASE_VOICE2_CALL)}, 339 {TO_NAME_INDEX(USECASE_VOLTE_CALL)}, 340 {TO_NAME_INDEX(USECASE_QCHAT_CALL)}, 341 {TO_NAME_INDEX(USECASE_VOWLAN_CALL)}, 342 {TO_NAME_INDEX(USECASE_INCALL_REC_UPLINK)}, 343 {TO_NAME_INDEX(USECASE_INCALL_REC_DOWNLINK)}, 344 {TO_NAME_INDEX(USECASE_INCALL_REC_UPLINK_AND_DOWNLINK)}, 345 {TO_NAME_INDEX(USECASE_AUDIO_HFP_SCO)}, 346}; 347 348#define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL) 349#define LOW_LATENCY_PLATFORM_DELAY (13*1000LL) 350 351static pthread_once_t check_op_once_ctl = PTHREAD_ONCE_INIT; 352static bool is_tmus = false; 353 354static void check_operator() 355{ 356 char value[PROPERTY_VALUE_MAX]; 357 int mccmnc; 358 property_get("gsm.sim.operator.numeric",value,"0"); 359 mccmnc = atoi(value); 360 ALOGD("%s: tmus mccmnc %d", __func__, mccmnc); 361 switch(mccmnc) { 362 /* TMUS MCC(310), MNC(490, 260, 026) */ 363 case 310490: 364 case 310260: 365 case 310026: 366 /* Add new TMUS MNC(800, 660, 580, 310, 270, 250, 240, 230, 220, 210, 200, 160) */ 367 case 310800: 368 case 310660: 369 case 310580: 370 case 310310: 371 case 310270: 372 case 310250: 373 case 310240: 374 case 310230: 375 case 310220: 376 case 310210: 377 case 310200: 378 case 310160: 379 is_tmus = true; 380 break; 381 } 382} 383 384bool is_operator_tmus() 385{ 386 pthread_once(&check_op_once_ctl, check_operator); 387 return is_tmus; 388} 389 390static void set_echo_reference(struct audio_device *adev, bool enable) 391{ 392 if (enable) 393 audio_route_apply_and_update_path(adev->audio_route, "echo-reference"); 394 else 395 audio_route_reset_and_update_path(adev->audio_route, "echo-reference"); 396 397 ALOGV("Setting EC Reference: %d", enable); 398} 399 400static struct csd_data *open_csd_client(bool i2s_ext_modem) 401{ 402 struct csd_data *csd = calloc(1, sizeof(struct csd_data)); 403 404 csd->csd_client = dlopen(LIB_CSD_CLIENT, RTLD_NOW); 405 if (csd->csd_client == NULL) { 406 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_CSD_CLIENT); 407 goto error; 408 } else { 409 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_CSD_CLIENT); 410 411 csd->deinit = (deinit_t)dlsym(csd->csd_client, 412 "csd_client_deinit"); 413 if (csd->deinit == NULL) { 414 ALOGE("%s: dlsym error %s for csd_client_deinit", __func__, 415 dlerror()); 416 goto error; 417 } 418 csd->disable_device = (disable_device_t)dlsym(csd->csd_client, 419 "csd_client_disable_device"); 420 if (csd->disable_device == NULL) { 421 ALOGE("%s: dlsym error %s for csd_client_disable_device", 422 __func__, dlerror()); 423 goto error; 424 } 425 csd->enable_device_config = (enable_device_config_t)dlsym(csd->csd_client, 426 "csd_client_enable_device_config"); 427 if (csd->enable_device_config == NULL) { 428 ALOGE("%s: dlsym error %s for csd_client_enable_device_config", 429 __func__, dlerror()); 430 goto error; 431 } 432 csd->enable_device = (enable_device_t)dlsym(csd->csd_client, 433 "csd_client_enable_device"); 434 if (csd->enable_device == NULL) { 435 ALOGE("%s: dlsym error %s for csd_client_enable_device", 436 __func__, dlerror()); 437 goto error; 438 } 439 csd->start_voice = (start_voice_t)dlsym(csd->csd_client, 440 "csd_client_start_voice"); 441 if (csd->start_voice == NULL) { 442 ALOGE("%s: dlsym error %s for csd_client_start_voice", 443 __func__, dlerror()); 444 goto error; 445 } 446 csd->stop_voice = (stop_voice_t)dlsym(csd->csd_client, 447 "csd_client_stop_voice"); 448 if (csd->stop_voice == NULL) { 449 ALOGE("%s: dlsym error %s for csd_client_stop_voice", 450 __func__, dlerror()); 451 goto error; 452 } 453 csd->volume = (volume_t)dlsym(csd->csd_client, 454 "csd_client_volume"); 455 if (csd->volume == NULL) { 456 ALOGE("%s: dlsym error %s for csd_client_volume", 457 __func__, dlerror()); 458 goto error; 459 } 460 csd->mic_mute = (mic_mute_t)dlsym(csd->csd_client, 461 "csd_client_mic_mute"); 462 if (csd->mic_mute == NULL) { 463 ALOGE("%s: dlsym error %s for csd_client_mic_mute", 464 __func__, dlerror()); 465 goto error; 466 } 467 csd->slow_talk = (slow_talk_t)dlsym(csd->csd_client, 468 "csd_client_slow_talk"); 469 if (csd->slow_talk == NULL) { 470 ALOGE("%s: dlsym error %s for csd_client_slow_talk", 471 __func__, dlerror()); 472 goto error; 473 } 474 csd->start_playback = (start_playback_t)dlsym(csd->csd_client, 475 "csd_client_start_playback"); 476 if (csd->start_playback == NULL) { 477 ALOGE("%s: dlsym error %s for csd_client_start_playback", 478 __func__, dlerror()); 479 goto error; 480 } 481 csd->stop_playback = (stop_playback_t)dlsym(csd->csd_client, 482 "csd_client_stop_playback"); 483 if (csd->stop_playback == NULL) { 484 ALOGE("%s: dlsym error %s for csd_client_stop_playback", 485 __func__, dlerror()); 486 goto error; 487 } 488 csd->start_record = (start_record_t)dlsym(csd->csd_client, 489 "csd_client_start_record"); 490 if (csd->start_record == NULL) { 491 ALOGE("%s: dlsym error %s for csd_client_start_record", 492 __func__, dlerror()); 493 goto error; 494 } 495 csd->stop_record = (stop_record_t)dlsym(csd->csd_client, 496 "csd_client_stop_record"); 497 if (csd->stop_record == NULL) { 498 ALOGE("%s: dlsym error %s for csd_client_stop_record", 499 __func__, dlerror()); 500 goto error; 501 } 502 503 csd->get_sample_rate = (get_sample_rate_t)dlsym(csd->csd_client, 504 "csd_client_get_sample_rate"); 505 if (csd->get_sample_rate == NULL) { 506 ALOGE("%s: dlsym error %s for csd_client_get_sample_rate", 507 __func__, dlerror()); 508 509 goto error; 510 } 511 512 csd->init = (init_t)dlsym(csd->csd_client, "csd_client_init"); 513 514 if (csd->init == NULL) { 515 ALOGE("%s: dlsym error %s for csd_client_init", 516 __func__, dlerror()); 517 goto error; 518 } else { 519 csd->init(i2s_ext_modem); 520 } 521 } 522 return csd; 523 524error: 525 free(csd); 526 csd = NULL; 527 return csd; 528} 529 530void close_csd_client(struct csd_data *csd) 531{ 532 if (csd != NULL) { 533 csd->deinit(); 534 dlclose(csd->csd_client); 535 free(csd); 536 csd = NULL; 537 } 538} 539 540static void platform_csd_init(struct platform_data *my_data) 541{ 542#ifdef PLATFORM_MSM8084 543 int32_t modems, (*count_modems)(void); 544 const char *name = "libdetectmodem.so"; 545 const char *func = "count_modems"; 546 const char *error; 547 548 my_data->csd = NULL; 549 550 void *lib = dlopen(name, RTLD_NOW); 551 error = dlerror(); 552 if (!lib) { 553 ALOGE("%s: could not find %s: %s", __func__, name, error); 554 return; 555 } 556 557 count_modems = NULL; 558 *(void **)(&count_modems) = dlsym(lib, func); 559 error = dlerror(); 560 if (!count_modems) { 561 ALOGE("%s: could not find symbol %s in %s: %s", 562 __func__, func, name, error); 563 goto done; 564 } 565 566 modems = count_modems(); 567 if (modems < 0) { 568 ALOGE("%s: count_modems failed\n", __func__); 569 goto done; 570 } 571 572 ALOGD("%s: num_modems %d\n", __func__, modems); 573 if (modems > 0) 574 my_data->csd = open_csd_client(false /*is_i2s_ext_modem*/); 575 576done: 577 dlclose(lib); 578#else 579 my_data->csd = NULL; 580#endif 581} 582 583static void set_platform_defaults(struct platform_data * my_data) 584{ 585 int32_t dev; 586 for (dev = 0; dev < SND_DEVICE_MAX; dev++) { 587 backend_table[dev] = NULL; 588 } 589 590 // TBD - do these go to the platform-info.xml file. 591 // will help in avoiding strdups here 592 backend_table[SND_DEVICE_IN_BT_SCO_MIC] = strdup("bt-sco"); 593 backend_table[SND_DEVICE_OUT_BT_SCO] = strdup("bt-sco"); 594 backend_table[SND_DEVICE_OUT_HDMI] = strdup("hdmi"); 595 backend_table[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = strdup("speaker-and-hdmi"); 596 backend_table[SND_DEVICE_OUT_BT_SCO_WB] = strdup("bt-sco-wb"); 597 backend_table[SND_DEVICE_IN_BT_SCO_MIC_WB] = strdup("bt-sco-wb"); 598 599 if (my_data->ext_speaker) { 600 backend_table[SND_DEVICE_OUT_SPEAKER] = strdup("speaker"); 601 backend_table[SND_DEVICE_OUT_VOICE_SPEAKER] = strdup("speaker"); 602 backend_table[SND_DEVICE_OUT_SPEAKER_REVERSE] = strdup("speaker"); 603 backend_table[SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = 604 strdup("speaker-and-headphones"); 605 } 606 607 if (my_data->ext_earpiece) { 608 backend_table[SND_DEVICE_OUT_VOICE_HANDSET] = strdup("handset"); 609 backend_table[SND_DEVICE_OUT_VOICE_HAC_HANDSET] = strdup("handset"); 610 backend_table[SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = strdup("handset"); 611 backend_table[SND_DEVICE_OUT_HANDSET] = strdup("handset"); 612 backend_table[SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = strdup("handset"); 613 } 614} 615 616void *platform_init(struct audio_device *adev) 617{ 618 char value[PROPERTY_VALUE_MAX]; 619 struct platform_data *my_data; 620 int retry_num = 0, snd_card_num = 0; 621 const char *snd_card_name; 622 623 while (snd_card_num < MAX_SND_CARD) { 624 adev->mixer = mixer_open(snd_card_num); 625 626 while (!adev->mixer && retry_num < RETRY_NUMBER) { 627 usleep(RETRY_US); 628 adev->mixer = mixer_open(snd_card_num); 629 retry_num++; 630 } 631 632 if (!adev->mixer) { 633 ALOGE("%s: Unable to open the mixer card: %d", __func__, 634 snd_card_num); 635 retry_num = 0; 636 snd_card_num++; 637 continue; 638 } 639 640 snd_card_name = mixer_get_name(adev->mixer); 641 ALOGD("%s: snd_card_name: %s", __func__, snd_card_name); 642 643 adev->audio_route = audio_route_init(snd_card_num, MIXER_XML_PATH); 644 if (!adev->audio_route) { 645 ALOGE("%s: Failed to init audio route controls, aborting.", __func__); 646 return NULL; 647 } 648 adev->snd_card = snd_card_num; 649 ALOGD("%s: Opened sound card:%d", __func__, snd_card_num); 650 break; 651 } 652 653 if (snd_card_num >= MAX_SND_CARD) { 654 ALOGE("%s: Unable to find correct sound card, aborting.", __func__); 655 return NULL; 656 } 657 658 my_data = calloc(1, sizeof(struct platform_data)); 659 660 my_data->adev = adev; 661 my_data->dualmic_config = DUALMIC_CONFIG_NONE; 662 my_data->fluence_in_spkr_mode = false; 663 my_data->fluence_in_voice_call = false; 664 my_data->fluence_in_voice_comm = false; 665 my_data->fluence_in_voice_rec = false; 666 667 /* 668 * The default assumption is that earpiece (handset), speaker and headphones 669 * devices are connected to internal HW codec and communicated through 670 * slimbus backend. If any platform communicates with speaker or earpiece 671 * or headphones through non-slimbus backend such as MI2S or AUXPCM etc., 672 * the ext_xxxx flags must be set accordingly. 673 */ 674 if (strstr(snd_card_name, "tfa9890_stereo")) { 675 my_data->ext_speaker = true; 676 my_data->ext_earpiece = true; 677 } else if (strstr(snd_card_name, "tfa9890")) { 678 my_data->ext_speaker = true; 679 } 680 681 property_get("persist.audio.dualmic.config",value,""); 682 if (!strcmp("broadside", value)) { 683 ALOGE("%s: Unsupported dualmic configuration", __func__); 684 } else if (!strcmp("endfire", value)) { 685 my_data->dualmic_config = DUALMIC_CONFIG_ENDFIRE; 686 } 687 688 if (my_data->dualmic_config != DUALMIC_CONFIG_NONE) { 689 property_get("persist.audio.fluence.voicecall",value,""); 690 if (!strcmp("true", value)) { 691 my_data->fluence_in_voice_call = true; 692 } 693 694 property_get("persist.audio.fluence.voicecomm",value,""); 695 if (!strcmp("true", value)) { 696 my_data->fluence_in_voice_comm = true; 697 } 698 699 property_get("persist.audio.fluence.voicerec",value,""); 700 if (!strcmp("true", value)) { 701 my_data->fluence_in_voice_rec = true; 702 } 703 704 property_get("persist.audio.fluence.speaker",value,""); 705 if (!strcmp("true", value)) { 706 my_data->fluence_in_spkr_mode = true; 707 } 708 } 709 710 my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW); 711 if (my_data->acdb_handle == NULL) { 712 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_ACDB_LOADER); 713 } else { 714 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_ACDB_LOADER); 715 my_data->acdb_deallocate = (acdb_deallocate_t)dlsym(my_data->acdb_handle, 716 "acdb_loader_deallocate_ACDB"); 717 if (!my_data->acdb_deallocate) 718 ALOGE("%s: Could not find the symbol acdb_loader_deallocate_ACDB from %s", 719 __func__, LIB_ACDB_LOADER); 720 721 my_data->acdb_send_audio_cal = (acdb_send_audio_cal_t)dlsym(my_data->acdb_handle, 722 "acdb_loader_send_audio_cal"); 723 if (!my_data->acdb_send_audio_cal) 724 ALOGE("%s: Could not find the symbol acdb_send_audio_cal from %s", 725 __func__, LIB_ACDB_LOADER); 726 727 my_data->acdb_send_voice_cal = (acdb_send_voice_cal_t)dlsym(my_data->acdb_handle, 728 "acdb_loader_send_voice_cal"); 729 if (!my_data->acdb_send_voice_cal) 730 ALOGE("%s: Could not find the symbol acdb_loader_send_voice_cal from %s", 731 __func__, LIB_ACDB_LOADER); 732 733 my_data->acdb_reload_vocvoltable = (acdb_reload_vocvoltable_t)dlsym(my_data->acdb_handle, 734 "acdb_loader_reload_vocvoltable"); 735 if (!my_data->acdb_reload_vocvoltable) 736 ALOGE("%s: Could not find the symbol acdb_loader_reload_vocvoltable from %s", 737 __func__, LIB_ACDB_LOADER); 738#ifdef PLATFORM_MSM8084 739 my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle, 740 "acdb_loader_init_v2"); 741 if (my_data->acdb_init == NULL) 742 ALOGE("%s: dlsym error %s for acdb_loader_init_v2", __func__, dlerror()); 743 else 744 my_data->acdb_init((char *)snd_card_name); 745#else 746 my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle, 747 "acdb_loader_init_ACDB"); 748 if (my_data->acdb_init == NULL) 749 ALOGE("%s: dlsym error %s for acdb_loader_init_ACDB", __func__, dlerror()); 750 else 751 my_data->acdb_init(); 752#endif 753 754 } 755 756 set_platform_defaults(my_data); 757 758 /* Initialize platform specific ids and/or backends*/ 759 platform_info_init(); 760 761 /* load csd client */ 762 platform_csd_init(my_data); 763 764 return my_data; 765} 766 767void platform_deinit(void *platform) 768{ 769 struct platform_data *my_data = (struct platform_data *)platform; 770 close_csd_client(my_data->csd); 771 free(platform); 772} 773 774const char *platform_get_snd_device_name(snd_device_t snd_device) 775{ 776 if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX) 777 return device_table[snd_device]; 778 else 779 return ""; 780} 781 782void platform_add_backend_name(void *platform, char *mixer_path, 783 snd_device_t snd_device) 784{ 785 struct platform_data *my_data = (struct platform_data *)platform; 786 787 if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) { 788 ALOGE("%s: Invalid snd_device = %d", __func__, snd_device); 789 return; 790 } 791 792 const char * suffix = backend_table[snd_device]; 793 794 if (suffix != NULL) { 795 strcat(mixer_path, " "); 796 strcat(mixer_path, suffix); 797 } 798} 799 800int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type) 801{ 802 int device_id; 803 if (device_type == PCM_PLAYBACK) 804 device_id = pcm_device_table[usecase][0]; 805 else 806 device_id = pcm_device_table[usecase][1]; 807 return device_id; 808} 809 810static int find_index(const struct name_to_index * table, int32_t len, 811 const char * name) 812{ 813 int ret = 0; 814 int32_t i; 815 816 if (table == NULL) { 817 ALOGE("%s: table is NULL", __func__); 818 ret = -ENODEV; 819 goto done; 820 } 821 822 if (name == NULL) { 823 ALOGE("null key"); 824 ret = -ENODEV; 825 goto done; 826 } 827 828 for (i=0; i < len; i++) { 829 if (!strcmp(table[i].name, name)) { 830 ret = table[i].index; 831 goto done; 832 } 833 } 834 ALOGE("%s: Could not find index for name = %s", 835 __func__, name); 836 ret = -ENODEV; 837done: 838 return ret; 839} 840 841int platform_get_snd_device_index(char *device_name) 842{ 843 return find_index(snd_device_name_index, SND_DEVICE_MAX, device_name); 844} 845 846int platform_get_usecase_index(const char *usecase_name) 847{ 848 return find_index(usecase_name_index, AUDIO_USECASE_MAX, usecase_name); 849} 850 851int platform_set_snd_device_acdb_id(snd_device_t snd_device, unsigned int acdb_id) 852{ 853 int ret = 0; 854 855 if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) { 856 ALOGE("%s: Invalid snd_device = %d", 857 __func__, snd_device); 858 ret = -EINVAL; 859 goto done; 860 } 861 862 acdb_device_table[snd_device] = acdb_id; 863done: 864 return ret; 865} 866 867int platform_send_audio_calibration(void *platform, snd_device_t snd_device) 868{ 869 struct platform_data *my_data = (struct platform_data *)platform; 870 int acdb_dev_id, acdb_dev_type; 871 872 acdb_dev_id = acdb_device_table[snd_device]; 873 if (acdb_dev_id < 0) { 874 ALOGE("%s: Could not find acdb id for device(%d)", 875 __func__, snd_device); 876 return -EINVAL; 877 } 878 if (my_data->acdb_send_audio_cal) { 879 ALOGD("%s: sending audio calibration for snd_device(%d) acdb_id(%d)", 880 __func__, snd_device, acdb_dev_id); 881 if (snd_device >= SND_DEVICE_OUT_BEGIN && 882 snd_device < SND_DEVICE_OUT_END) 883 acdb_dev_type = ACDB_DEV_TYPE_OUT; 884 else 885 acdb_dev_type = ACDB_DEV_TYPE_IN; 886 my_data->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type); 887 } 888 return 0; 889} 890 891int platform_switch_voice_call_device_pre(void *platform) 892{ 893 struct platform_data *my_data = (struct platform_data *)platform; 894 int ret = 0; 895 896 if (my_data->csd != NULL && 897 my_data->adev->mode == AUDIO_MODE_IN_CALL) { 898 /* This must be called before disabling mixer controls on APQ side */ 899 ret = my_data->csd->disable_device(); 900 if (ret < 0) { 901 ALOGE("%s: csd_client_disable_device, failed, error %d", 902 __func__, ret); 903 } 904 } 905 return ret; 906} 907 908int platform_switch_voice_call_enable_device_config(void *platform, 909 snd_device_t out_snd_device, 910 snd_device_t in_snd_device) 911{ 912 struct platform_data *my_data = (struct platform_data *)platform; 913 int acdb_rx_id, acdb_tx_id; 914 int ret = 0; 915 916 if (my_data->csd == NULL) 917 return ret; 918 919 acdb_rx_id = acdb_device_table[out_snd_device]; 920 921 acdb_tx_id = acdb_device_table[in_snd_device]; 922 923 if (acdb_rx_id > 0 && acdb_tx_id > 0) { 924 ret = my_data->csd->enable_device_config(acdb_rx_id, acdb_tx_id); 925 if (ret < 0) { 926 ALOGE("%s: csd_enable_device_config, failed, error %d", 927 __func__, ret); 928 } 929 } else { 930 ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__, 931 acdb_rx_id, acdb_tx_id); 932 } 933 934 return ret; 935} 936 937int platform_switch_voice_call_device_post(void *platform, 938 snd_device_t out_snd_device, 939 snd_device_t in_snd_device) 940{ 941 struct platform_data *my_data = (struct platform_data *)platform; 942 int acdb_rx_id, acdb_tx_id; 943 944 if (my_data->acdb_send_voice_cal == NULL) { 945 ALOGE("%s: dlsym error for acdb_send_voice_call", __func__); 946 } else { 947 acdb_rx_id = acdb_device_table[out_snd_device]; 948 acdb_tx_id = acdb_device_table[in_snd_device]; 949 950 if (acdb_rx_id > 0 && acdb_tx_id > 0) 951 my_data->acdb_send_voice_cal(acdb_rx_id, acdb_tx_id); 952 else 953 ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__, 954 acdb_rx_id, acdb_tx_id); 955 } 956 957 return 0; 958} 959 960int platform_switch_voice_call_usecase_route_post(void *platform, 961 snd_device_t out_snd_device, 962 snd_device_t in_snd_device) 963{ 964 struct platform_data *my_data = (struct platform_data *)platform; 965 int acdb_rx_id, acdb_tx_id; 966 int ret = 0; 967 968 if (my_data->csd == NULL) 969 return ret; 970 971 acdb_rx_id = acdb_device_table[out_snd_device]; 972 973 acdb_tx_id = acdb_device_table[in_snd_device]; 974 975 if (acdb_rx_id > 0 && acdb_tx_id > 0) { 976 ret = my_data->csd->enable_device(acdb_rx_id, acdb_tx_id, 977 my_data->adev->acdb_settings); 978 if (ret < 0) { 979 ALOGE("%s: csd_enable_device, failed, error %d", __func__, ret); 980 } 981 } else { 982 ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__, 983 acdb_rx_id, acdb_tx_id); 984 } 985 986 return ret; 987} 988 989int platform_start_voice_call(void *platform, uint32_t vsid) 990{ 991 struct platform_data *my_data = (struct platform_data *)platform; 992 int ret = 0; 993 994 if (my_data->csd != NULL) { 995 ret = my_data->csd->start_voice(vsid); 996 if (ret < 0) { 997 ALOGE("%s: csd_start_voice error %d\n", __func__, ret); 998 } 999 } 1000 return ret; 1001} 1002 1003int platform_stop_voice_call(void *platform, uint32_t vsid) 1004{ 1005 struct platform_data *my_data = (struct platform_data *)platform; 1006 int ret = 0; 1007 1008 if (my_data->csd != NULL) { 1009 ret = my_data->csd->stop_voice(vsid); 1010 if (ret < 0) { 1011 ALOGE("%s: csd_stop_voice error %d\n", __func__, ret); 1012 } 1013 } 1014 return ret; 1015} 1016 1017int platform_get_sample_rate(void *platform, uint32_t *rate) 1018{ 1019 struct platform_data *my_data = (struct platform_data *)platform; 1020 int ret = 0; 1021 1022 if (my_data->csd != NULL) { 1023 ret = my_data->csd->get_sample_rate(rate); 1024 if (ret < 0) { 1025 ALOGE("%s: csd_get_sample_rate error %d\n", __func__, ret); 1026 } 1027 } 1028 return ret; 1029} 1030 1031int platform_set_voice_volume(void *platform, int volume) 1032{ 1033 struct platform_data *my_data = (struct platform_data *)platform; 1034 struct audio_device *adev = my_data->adev; 1035 struct mixer_ctl *ctl; 1036 const char *mixer_ctl_name = "Voice Rx Gain"; 1037 int vol_index = 0, ret = 0; 1038 uint32_t set_values[ ] = {0, 1039 ALL_SESSION_VSID, 1040 DEFAULT_VOLUME_RAMP_DURATION_MS}; 1041 1042 // Voice volume levels are mapped to adsp volume levels as follows. 1043 // 100 -> 5, 80 -> 4, 60 -> 3, 40 -> 2, 20 -> 1 0 -> 0 1044 // But this values don't changed in kernel. So, below change is need. 1045 vol_index = (int)percent_to_index(volume, MIN_VOL_INDEX, MAX_VOL_INDEX); 1046 set_values[0] = vol_index; 1047 1048 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name); 1049 if (!ctl) { 1050 ALOGE("%s: Could not get ctl for mixer cmd - %s", 1051 __func__, mixer_ctl_name); 1052 return -EINVAL; 1053 } 1054 ALOGV("Setting voice volume index: %d", set_values[0]); 1055 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values)); 1056 1057 if (my_data->csd != NULL) { 1058 ret = my_data->csd->volume(ALL_SESSION_VSID, volume, 1059 DEFAULT_VOLUME_RAMP_DURATION_MS); 1060 if (ret < 0) { 1061 ALOGE("%s: csd_volume error %d", __func__, ret); 1062 } 1063 } 1064 return ret; 1065} 1066 1067int platform_set_mic_mute(void *platform, bool state) 1068{ 1069 struct platform_data *my_data = (struct platform_data *)platform; 1070 struct audio_device *adev = my_data->adev; 1071 struct mixer_ctl *ctl; 1072 const char *mixer_ctl_name = "Voice Tx Mute"; 1073 int ret = 0; 1074 uint32_t set_values[ ] = {0, 1075 ALL_SESSION_VSID, 1076 DEFAULT_MUTE_RAMP_DURATION_MS}; 1077 1078 if (adev->mode != AUDIO_MODE_IN_CALL) 1079 return 0; 1080 1081 set_values[0] = state; 1082 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name); 1083 if (!ctl) { 1084 ALOGE("%s: Could not get ctl for mixer cmd - %s", 1085 __func__, mixer_ctl_name); 1086 return -EINVAL; 1087 } 1088 ALOGV("Setting voice mute state: %d", state); 1089 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values)); 1090 1091 if (my_data->csd != NULL) { 1092 ret = my_data->csd->mic_mute(ALL_SESSION_VSID, state, 1093 DEFAULT_MUTE_RAMP_DURATION_MS); 1094 if (ret < 0) { 1095 ALOGE("%s: csd_mic_mute error %d", __func__, ret); 1096 } 1097 } 1098 return ret; 1099} 1100 1101int platform_set_device_mute(void *platform, bool state, char *dir) 1102{ 1103 struct platform_data *my_data = (struct platform_data *)platform; 1104 struct audio_device *adev = my_data->adev; 1105 struct mixer_ctl *ctl; 1106 char *mixer_ctl_name = NULL; 1107 int ret = 0; 1108 uint32_t set_values[ ] = {0, 1109 ALL_SESSION_VSID, 1110 0}; 1111 if(dir == NULL) { 1112 ALOGE("%s: Invalid direction:%s", __func__, dir); 1113 return -EINVAL; 1114 } 1115 1116 if (!strncmp("rx", dir, sizeof("rx"))) { 1117 mixer_ctl_name = "Voice Rx Device Mute"; 1118 } else if (!strncmp("tx", dir, sizeof("tx"))) { 1119 mixer_ctl_name = "Voice Tx Device Mute"; 1120 } else { 1121 return -EINVAL; 1122 } 1123 1124 set_values[0] = state; 1125 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name); 1126 if (!ctl) { 1127 ALOGE("%s: Could not get ctl for mixer cmd - %s", 1128 __func__, mixer_ctl_name); 1129 return -EINVAL; 1130 } 1131 1132 ALOGV("%s: Setting device mute state: %d, mixer ctrl:%s", 1133 __func__,state, mixer_ctl_name); 1134 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values)); 1135 1136 return ret; 1137} 1138 1139snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices) 1140{ 1141 struct platform_data *my_data = (struct platform_data *)platform; 1142 struct audio_device *adev = my_data->adev; 1143 audio_mode_t mode = adev->mode; 1144 snd_device_t snd_device = SND_DEVICE_NONE; 1145 1146 ALOGV("%s: enter: output devices(%#x)", __func__, devices); 1147 if (devices == AUDIO_DEVICE_NONE || 1148 devices & AUDIO_DEVICE_BIT_IN) { 1149 ALOGV("%s: Invalid output devices (%#x)", __func__, devices); 1150 goto exit; 1151 } 1152 1153 if (mode == AUDIO_MODE_IN_CALL) { 1154 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE || 1155 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET || 1156 devices & AUDIO_DEVICE_OUT_LINE) { 1157 if (adev->voice.tty_mode == TTY_MODE_FULL) 1158 snd_device = SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES; 1159 else if (adev->voice.tty_mode == TTY_MODE_VCO) 1160 snd_device = SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES; 1161 else if (adev->voice.tty_mode == TTY_MODE_HCO) 1162 snd_device = SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET; 1163 else { 1164 if (devices & AUDIO_DEVICE_OUT_LINE) 1165 snd_device = SND_DEVICE_OUT_VOICE_LINE; 1166 else 1167 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES; 1168 } 1169 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) { 1170 if (adev->bt_wb_speech_enabled) { 1171 snd_device = SND_DEVICE_OUT_BT_SCO_WB; 1172 } else { 1173 snd_device = SND_DEVICE_OUT_BT_SCO; 1174 } 1175 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) { 1176 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER; 1177 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) { 1178 if(adev->voice.hac) 1179 snd_device = SND_DEVICE_OUT_VOICE_HAC_HANDSET; 1180 else if (is_operator_tmus()) 1181 snd_device = SND_DEVICE_OUT_VOICE_HANDSET_TMUS; 1182 else 1183 snd_device = SND_DEVICE_OUT_VOICE_HANDSET; 1184 } 1185 if (snd_device != SND_DEVICE_NONE) { 1186 goto exit; 1187 } 1188 } 1189 1190 if (popcount(devices) == 2) { 1191 if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE | 1192 AUDIO_DEVICE_OUT_SPEAKER)) { 1193 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES; 1194 } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET | 1195 AUDIO_DEVICE_OUT_SPEAKER)) { 1196 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES; 1197 } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL | 1198 AUDIO_DEVICE_OUT_SPEAKER)) { 1199 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI; 1200 } else { 1201 ALOGE("%s: Invalid combo device(%#x)", __func__, devices); 1202 goto exit; 1203 } 1204 if (snd_device != SND_DEVICE_NONE) { 1205 goto exit; 1206 } 1207 } 1208 1209 if (popcount(devices) != 1) { 1210 ALOGE("%s: Invalid output devices(%#x)", __func__, devices); 1211 goto exit; 1212 } 1213 1214 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE || 1215 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) { 1216 snd_device = SND_DEVICE_OUT_HEADPHONES; 1217 } else if (devices & AUDIO_DEVICE_OUT_LINE) { 1218 snd_device = SND_DEVICE_OUT_LINE; 1219 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) { 1220 if (adev->speaker_lr_swap) 1221 snd_device = SND_DEVICE_OUT_SPEAKER_REVERSE; 1222 else 1223 snd_device = SND_DEVICE_OUT_SPEAKER; 1224 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) { 1225 if (adev->bt_wb_speech_enabled) { 1226 snd_device = SND_DEVICE_OUT_BT_SCO_WB; 1227 } else { 1228 snd_device = SND_DEVICE_OUT_BT_SCO; 1229 } 1230 } else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) { 1231 snd_device = SND_DEVICE_OUT_HDMI ; 1232 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) { 1233 /*HAC support for voice-ish audio (eg visual voicemail)*/ 1234 if(adev->voice.hac) 1235 snd_device = SND_DEVICE_OUT_VOICE_HAC_HANDSET; 1236 else 1237 snd_device = SND_DEVICE_OUT_HANDSET; 1238 } else { 1239 ALOGE("%s: Unknown device(s) %#x", __func__, devices); 1240 } 1241exit: 1242 ALOGV("%s: exit: snd_device(%s)", __func__, device_table[snd_device]); 1243 return snd_device; 1244} 1245 1246snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device) 1247{ 1248 struct platform_data *my_data = (struct platform_data *)platform; 1249 struct audio_device *adev = my_data->adev; 1250 audio_source_t source = (adev->active_input == NULL) ? 1251 AUDIO_SOURCE_DEFAULT : adev->active_input->source; 1252 1253 audio_mode_t mode = adev->mode; 1254 audio_devices_t in_device = ((adev->active_input == NULL) ? 1255 AUDIO_DEVICE_NONE : adev->active_input->device) 1256 & ~AUDIO_DEVICE_BIT_IN; 1257 audio_channel_mask_t channel_mask = (adev->active_input == NULL) ? 1258 AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask; 1259 snd_device_t snd_device = SND_DEVICE_NONE; 1260 int channel_count = popcount(channel_mask); 1261 1262 ALOGV("%s: enter: out_device(%#x) in_device(%#x)", 1263 __func__, out_device, in_device); 1264 if (mode == AUDIO_MODE_IN_CALL) { 1265 if (out_device == AUDIO_DEVICE_NONE) { 1266 ALOGE("%s: No output device set for voice call", __func__); 1267 goto exit; 1268 } 1269 if (adev->voice.tty_mode != TTY_MODE_OFF) { 1270 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE || 1271 out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET || 1272 out_device & AUDIO_DEVICE_OUT_LINE) { 1273 switch (adev->voice.tty_mode) { 1274 case TTY_MODE_FULL: 1275 snd_device = SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC; 1276 break; 1277 case TTY_MODE_VCO: 1278 snd_device = SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC; 1279 break; 1280 case TTY_MODE_HCO: 1281 snd_device = SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC; 1282 break; 1283 default: 1284 ALOGE("%s: Invalid TTY mode (%#x)", __func__, adev->voice.tty_mode); 1285 } 1286 goto exit; 1287 } 1288 } 1289 if (out_device & AUDIO_DEVICE_OUT_EARPIECE || 1290 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) { 1291 if (my_data->fluence_in_voice_call == false) { 1292 snd_device = SND_DEVICE_IN_HANDSET_MIC; 1293 set_echo_reference(adev, true); 1294 } else { 1295 if (is_operator_tmus()) 1296 snd_device = SND_DEVICE_IN_VOICE_DMIC_TMUS; 1297 else 1298 snd_device = SND_DEVICE_IN_VOICE_DMIC; 1299 } 1300 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) { 1301 snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC; 1302 } else if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) { 1303 if (adev->bt_wb_speech_enabled) { 1304 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB; 1305 } else { 1306 snd_device = SND_DEVICE_IN_BT_SCO_MIC; 1307 } 1308 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) { 1309 if (my_data->fluence_in_voice_call && my_data->fluence_in_spkr_mode && 1310 my_data->dualmic_config != DUALMIC_CONFIG_NONE) { 1311 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC; 1312 } else { 1313 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC; 1314 set_echo_reference(adev, true); 1315 } 1316 } 1317 } else if (source == AUDIO_SOURCE_CAMCORDER) { 1318 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC || 1319 in_device & AUDIO_DEVICE_IN_BACK_MIC) { 1320 snd_device = SND_DEVICE_IN_CAMCORDER_MIC; 1321 } 1322 } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) { 1323 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) { 1324 if (my_data->dualmic_config != DUALMIC_CONFIG_NONE) { 1325 if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK) 1326 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_STEREO; 1327 else if (my_data->fluence_in_voice_rec && 1328 adev->active_input->enable_ns) 1329 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE; 1330 } 1331 1332 if (snd_device == SND_DEVICE_NONE) { 1333 if (adev->active_input->enable_ns) 1334 snd_device = SND_DEVICE_IN_VOICE_REC_MIC_NS; 1335 else 1336 snd_device = SND_DEVICE_IN_VOICE_REC_MIC; 1337 } 1338 } 1339 } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION) { 1340 if (out_device & AUDIO_DEVICE_OUT_SPEAKER) 1341 in_device = AUDIO_DEVICE_IN_BACK_MIC; 1342 if (adev->active_input) { 1343 if (adev->active_input->enable_aec && 1344 adev->active_input->enable_ns) { 1345 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) { 1346 if (my_data->fluence_in_spkr_mode && 1347 my_data->fluence_in_voice_comm && 1348 my_data->dualmic_config != DUALMIC_CONFIG_NONE) { 1349 snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS; 1350 } else 1351 snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS; 1352 } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) { 1353 if (my_data->fluence_in_voice_comm && 1354 my_data->dualmic_config != DUALMIC_CONFIG_NONE) { 1355 snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS; 1356 } else 1357 snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS; 1358 } 1359 set_echo_reference(adev, true); 1360 } else if (adev->active_input->enable_aec) { 1361 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) { 1362 if (my_data->fluence_in_spkr_mode && 1363 my_data->fluence_in_voice_comm && 1364 my_data->dualmic_config != DUALMIC_CONFIG_NONE) { 1365 snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC; 1366 } else 1367 snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC; 1368 } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) { 1369 if (my_data->fluence_in_voice_comm && 1370 my_data->dualmic_config != DUALMIC_CONFIG_NONE) { 1371 snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC; 1372 } else 1373 snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC; 1374 } 1375 set_echo_reference(adev, true); 1376 } else if (adev->active_input->enable_ns) { 1377 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) { 1378 if (my_data->fluence_in_spkr_mode && 1379 my_data->fluence_in_voice_comm && 1380 my_data->dualmic_config != DUALMIC_CONFIG_NONE) { 1381 snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS; 1382 } else 1383 snd_device = SND_DEVICE_IN_SPEAKER_MIC_NS; 1384 } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) { 1385 if (my_data->fluence_in_voice_comm && 1386 my_data->dualmic_config != DUALMIC_CONFIG_NONE) { 1387 snd_device = SND_DEVICE_IN_HANDSET_DMIC_NS; 1388 } else 1389 snd_device = SND_DEVICE_IN_HANDSET_MIC_NS; 1390 } 1391 set_echo_reference(adev, false); 1392 } else 1393 set_echo_reference(adev, false); 1394 } 1395 } else if (source == AUDIO_SOURCE_DEFAULT) { 1396 goto exit; 1397 } 1398 1399 1400 if (snd_device != SND_DEVICE_NONE) { 1401 goto exit; 1402 } 1403 1404 if (in_device != AUDIO_DEVICE_NONE && 1405 !(in_device & AUDIO_DEVICE_IN_VOICE_CALL) && 1406 !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) { 1407 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) { 1408 if (my_data->dualmic_config != DUALMIC_CONFIG_NONE && 1409 channel_count == 2) 1410 snd_device = SND_DEVICE_IN_HANDSET_DMIC_STEREO; 1411 else 1412 snd_device = SND_DEVICE_IN_HANDSET_MIC; 1413 } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) { 1414 if (my_data->dualmic_config != DUALMIC_CONFIG_NONE && 1415 channel_count == 2) 1416 snd_device = SND_DEVICE_IN_SPEAKER_DMIC_STEREO; 1417 else 1418 snd_device = SND_DEVICE_IN_SPEAKER_MIC; 1419 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) { 1420 snd_device = SND_DEVICE_IN_HEADSET_MIC; 1421 } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) { 1422 if (adev->bt_wb_speech_enabled) { 1423 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB; 1424 } else { 1425 snd_device = SND_DEVICE_IN_BT_SCO_MIC; 1426 } 1427 } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) { 1428 snd_device = SND_DEVICE_IN_HDMI_MIC; 1429 } else { 1430 ALOGE("%s: Unknown input device(s) %#x", __func__, in_device); 1431 ALOGW("%s: Using default handset-mic", __func__); 1432 snd_device = SND_DEVICE_IN_HANDSET_MIC; 1433 } 1434 } else { 1435 if (out_device & AUDIO_DEVICE_OUT_EARPIECE) { 1436 snd_device = SND_DEVICE_IN_HANDSET_MIC; 1437 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) { 1438 snd_device = SND_DEVICE_IN_HEADSET_MIC; 1439 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER || 1440 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE || 1441 out_device & AUDIO_DEVICE_OUT_LINE) { 1442 if (channel_count == 2) 1443 snd_device = SND_DEVICE_IN_SPEAKER_DMIC_STEREO; 1444 else 1445 snd_device = SND_DEVICE_IN_SPEAKER_MIC; 1446 } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) { 1447 if (adev->bt_wb_speech_enabled) { 1448 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB; 1449 } else { 1450 snd_device = SND_DEVICE_IN_BT_SCO_MIC; 1451 } 1452 } else if (out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL) { 1453 snd_device = SND_DEVICE_IN_HDMI_MIC; 1454 } else { 1455 ALOGE("%s: Unknown output device(s) %#x", __func__, out_device); 1456 ALOGW("%s: Using default handset-mic", __func__); 1457 snd_device = SND_DEVICE_IN_HANDSET_MIC; 1458 } 1459 } 1460exit: 1461 ALOGV("%s: exit: in_snd_device(%s)", __func__, device_table[snd_device]); 1462 return snd_device; 1463} 1464 1465int platform_set_hdmi_channels(void *platform, int channel_count) 1466{ 1467 struct platform_data *my_data = (struct platform_data *)platform; 1468 struct audio_device *adev = my_data->adev; 1469 struct mixer_ctl *ctl; 1470 const char *channel_cnt_str = NULL; 1471 const char *mixer_ctl_name = "HDMI_RX Channels"; 1472 switch (channel_count) { 1473 case 8: 1474 channel_cnt_str = "Eight"; break; 1475 case 7: 1476 channel_cnt_str = "Seven"; break; 1477 case 6: 1478 channel_cnt_str = "Six"; break; 1479 case 5: 1480 channel_cnt_str = "Five"; break; 1481 case 4: 1482 channel_cnt_str = "Four"; break; 1483 case 3: 1484 channel_cnt_str = "Three"; break; 1485 default: 1486 channel_cnt_str = "Two"; break; 1487 } 1488 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name); 1489 if (!ctl) { 1490 ALOGE("%s: Could not get ctl for mixer cmd - %s", 1491 __func__, mixer_ctl_name); 1492 return -EINVAL; 1493 } 1494 ALOGV("HDMI channel count: %s", channel_cnt_str); 1495 mixer_ctl_set_enum_by_string(ctl, channel_cnt_str); 1496 return 0; 1497} 1498 1499int platform_edid_get_max_channels(void *platform) 1500{ 1501 struct platform_data *my_data = (struct platform_data *)platform; 1502 struct audio_device *adev = my_data->adev; 1503 char block[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE]; 1504 char *sad = block; 1505 int num_audio_blocks; 1506 int channel_count; 1507 int max_channels = 0; 1508 int i, ret, count; 1509 1510 struct mixer_ctl *ctl; 1511 1512 ctl = mixer_get_ctl_by_name(adev->mixer, AUDIO_DATA_BLOCK_MIXER_CTL); 1513 if (!ctl) { 1514 ALOGE("%s: Could not get ctl for mixer cmd - %s", 1515 __func__, AUDIO_DATA_BLOCK_MIXER_CTL); 1516 return 0; 1517 } 1518 1519 mixer_ctl_update(ctl); 1520 1521 count = mixer_ctl_get_num_values(ctl); 1522 1523 /* Read SAD blocks, clamping the maximum size for safety */ 1524 if (count > (int)sizeof(block)) 1525 count = (int)sizeof(block); 1526 1527 ret = mixer_ctl_get_array(ctl, block, count); 1528 if (ret != 0) { 1529 ALOGE("%s: mixer_ctl_get_array() failed to get EDID info", __func__); 1530 return 0; 1531 } 1532 1533 /* Calculate the number of SAD blocks */ 1534 num_audio_blocks = count / SAD_BLOCK_SIZE; 1535 1536 for (i = 0; i < num_audio_blocks; i++) { 1537 /* Only consider LPCM blocks */ 1538 if ((sad[0] >> 3) != EDID_FORMAT_LPCM) { 1539 sad += 3; 1540 continue; 1541 } 1542 1543 channel_count = (sad[0] & 0x7) + 1; 1544 if (channel_count > max_channels) 1545 max_channels = channel_count; 1546 1547 /* Advance to next block */ 1548 sad += 3; 1549 } 1550 1551 return max_channels; 1552} 1553 1554int platform_set_incall_recording_session_id(void *platform, 1555 uint32_t session_id, int rec_mode) 1556{ 1557 int ret = 0; 1558 struct platform_data *my_data = (struct platform_data *)platform; 1559 struct audio_device *adev = my_data->adev; 1560 struct mixer_ctl *ctl; 1561 const char *mixer_ctl_name = "Voc VSID"; 1562 int num_ctl_values; 1563 int i; 1564 1565 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name); 1566 if (!ctl) { 1567 ALOGE("%s: Could not get ctl for mixer cmd - %s", 1568 __func__, mixer_ctl_name); 1569 ret = -EINVAL; 1570 } else { 1571 num_ctl_values = mixer_ctl_get_num_values(ctl); 1572 for (i = 0; i < num_ctl_values; i++) { 1573 if (mixer_ctl_set_value(ctl, i, session_id)) { 1574 ALOGV("Error: invalid session_id: %x", session_id); 1575 ret = -EINVAL; 1576 break; 1577 } 1578 } 1579 } 1580 1581 if (my_data->csd != NULL) { 1582 ret = my_data->csd->start_record(ALL_SESSION_VSID, rec_mode); 1583 if (ret < 0) { 1584 ALOGE("%s: csd_client_start_record failed, error %d", 1585 __func__, ret); 1586 } 1587 } 1588 1589 return ret; 1590} 1591 1592int platform_stop_incall_recording_usecase(void *platform) 1593{ 1594 int ret = 0; 1595 struct platform_data *my_data = (struct platform_data *)platform; 1596 1597 if (my_data->csd != NULL) { 1598 ret = my_data->csd->stop_record(ALL_SESSION_VSID); 1599 if (ret < 0) { 1600 ALOGE("%s: csd_client_stop_record failed, error %d", 1601 __func__, ret); 1602 } 1603 } 1604 1605 return ret; 1606} 1607 1608int platform_start_incall_music_usecase(void *platform) 1609{ 1610 int ret = 0; 1611 struct platform_data *my_data = (struct platform_data *)platform; 1612 1613 if (my_data->csd != NULL) { 1614 ret = my_data->csd->start_playback(ALL_SESSION_VSID); 1615 if (ret < 0) { 1616 ALOGE("%s: csd_client_start_playback failed, error %d", 1617 __func__, ret); 1618 } 1619 } 1620 1621 return ret; 1622} 1623 1624int platform_stop_incall_music_usecase(void *platform) 1625{ 1626 int ret = 0; 1627 struct platform_data *my_data = (struct platform_data *)platform; 1628 1629 if (my_data->csd != NULL) { 1630 ret = my_data->csd->stop_playback(ALL_SESSION_VSID); 1631 if (ret < 0) { 1632 ALOGE("%s: csd_client_stop_playback failed, error %d", 1633 __func__, ret); 1634 } 1635 } 1636 1637 return ret; 1638} 1639 1640/* Delay in Us */ 1641int64_t platform_render_latency(audio_usecase_t usecase) 1642{ 1643 switch (usecase) { 1644 case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER: 1645 return DEEP_BUFFER_PLATFORM_DELAY; 1646 case USECASE_AUDIO_PLAYBACK_LOW_LATENCY: 1647 return LOW_LATENCY_PLATFORM_DELAY; 1648 default: 1649 return 0; 1650 } 1651} 1652 1653int platform_set_snd_device_backend(snd_device_t device, const char *backend) 1654{ 1655 int ret = 0; 1656 1657 if ((device < SND_DEVICE_MIN) || (device >= SND_DEVICE_MAX)) { 1658 ALOGE("%s: Invalid snd_device = %d", 1659 __func__, device); 1660 ret = -EINVAL; 1661 goto done; 1662 } 1663 1664 if (backend_table[device]) { 1665 free(backend_table[device]); 1666 } 1667 backend_table[device] = strdup(backend); 1668done: 1669 return ret; 1670} 1671 1672int platform_set_usecase_pcm_id(audio_usecase_t usecase, int32_t type, int32_t pcm_id) 1673{ 1674 int ret = 0; 1675 if ((usecase <= USECASE_INVALID) || (usecase >= AUDIO_USECASE_MAX)) { 1676 ALOGE("%s: invalid usecase case idx %d", __func__, usecase); 1677 ret = -EINVAL; 1678 goto done; 1679 } 1680 1681 if ((type != 0) && (type != 1)) { 1682 ALOGE("%s: invalid usecase type", __func__); 1683 ret = -EINVAL; 1684 } 1685 pcm_device_table[usecase][type] = pcm_id; 1686done: 1687 return ret; 1688} 1689