1 /* 2 * Copyright (C) 2013-2016 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 "tfa_98xx" 18 /*#define LOG_NDEBUG 0*/ 19 #include <log/log.h> 20 21 #include <stdlib.h> 22 #include <audio_hw.h> 23 #include <dlfcn.h> 24 #include "audio_extn.h" 25 #include <platform.h> 26 #include <math.h> 27 28 #define LIB_SPEAKER_BUNDLE "/system/lib/libexTfa98xx.so" 29 30 31 enum exTfa98xx_Audio_Mode 32 { 33 Audio_Mode_None = -1, 34 Audio_Mode_Music_Normal, 35 Audio_Mode_Hfp_Client, 36 Audio_Mode_Voice, 37 Audio_Mode_Hs_Hfp, 38 Audio_Mode_Max 39 }; 40 typedef enum exTfa98xx_Audio_Mode exTfa98xx_audio_mode_t; 41 42 enum exTfa98xx_Func_Mode 43 { 44 Func_Mode_None = -1, 45 Func_Mode_Speaker, 46 Func_Mode_BT 47 }; 48 typedef enum exTfa98xx_Func_Mode exTfa98xx_func_mode_t; 49 50 #define I2S_CLOCK_ENABLE 1 51 #define I2S_CLOCK_DISABLE 0 52 #define HFP_MAX_VOLUME (15.000000) 53 #define TFA_98XX_HFP_VSETPS (5.0) 54 55 exTfa98xx_audio_mode_t current_audio_mode = Audio_Mode_None; 56 57 typedef int (*set_speaker_on_t)(exTfa98xx_audio_mode_t); 58 typedef int (*set_speaker_off_t)(void); 59 typedef int (*set_speaker_calibration_t)(int); 60 typedef void (*set_speaker_volume_step_t)(int, int); 61 62 63 struct speaker_data { 64 struct audio_device *adev; 65 void *speaker_bundle; 66 set_speaker_on_t set_speaker_on; 67 set_speaker_off_t set_speaker_off; 68 set_speaker_calibration_t set_speaker_calibration; 69 set_speaker_volume_step_t set_speaker_volume_step; 70 int ref_cnt[Audio_Mode_Max]; 71 int route_cnt[Audio_Mode_Max]; 72 bool update_ref_cnt; 73 }; 74 75 struct speaker_data *tfa98xx_speaker_data = NULL; 76 77 static struct speaker_data* open_speaker_bundle() 78 { 79 struct speaker_data *sd = calloc(1, sizeof(struct speaker_data)); 80 81 sd->speaker_bundle = dlopen(LIB_SPEAKER_BUNDLE, RTLD_NOW); 82 if (sd->speaker_bundle == NULL) { 83 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_SPEAKER_BUNDLE); 84 goto error; 85 } else { 86 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_SPEAKER_BUNDLE); 87 88 sd->set_speaker_on = (set_speaker_on_t)dlsym(sd->speaker_bundle, 89 "exTfa98xx_speakeron"); 90 if (sd->set_speaker_on == NULL) { 91 ALOGE("%s: dlsym error %s for exTfa98xx_speakeron", __func__, 92 dlerror()); 93 goto error; 94 } 95 sd->set_speaker_off = (set_speaker_off_t)dlsym(sd->speaker_bundle, 96 "exTfa98xx_speakeroff"); 97 if (sd->set_speaker_off == NULL) { 98 ALOGE("%s: dlsym error %s for exTfa98xx_speakeroff", __func__, 99 dlerror()); 100 goto error; 101 } 102 sd->set_speaker_volume_step = (set_speaker_volume_step_t)dlsym(sd->speaker_bundle, 103 "exTfa98xx_setvolumestep"); 104 if (sd->set_speaker_volume_step == NULL) { 105 ALOGE("%s: dlsym error %s for exTfa98xx_setvolumestep", 106 __func__, dlerror()); 107 goto error; 108 } 109 sd->set_speaker_calibration = (set_speaker_calibration_t)dlsym(sd->speaker_bundle, 110 "exTfa98xx_calibration"); 111 if (sd->set_speaker_calibration == NULL) { 112 ALOGE("%s: dlsym error %s for exTfa98xx_calibration", 113 __func__, dlerror()); 114 goto error; 115 } 116 } 117 return sd; 118 119 error: 120 free(sd); 121 return 0; 122 } 123 124 static void close_speaker_bundle(struct speaker_data *sd) 125 { 126 if (sd != NULL) { 127 dlclose(sd->speaker_bundle); 128 free(sd); 129 sd = NULL; 130 } 131 } 132 133 static int adev_i2s_clock_operation(int enable, struct audio_device *adev, char *paths) 134 { 135 int ret = -1; 136 137 ALOGD("%s: mixer paths is: %s, enable: %d\n", __func__, paths, enable); 138 if(I2S_CLOCK_ENABLE == enable) { 139 ret = audio_route_apply_and_update_path(adev->audio_route, paths); 140 if(ret) { 141 ALOGE("%s: audio_route_apply_and_update_path return %d\n", __func__, ret); 142 return ret; 143 } 144 } else { 145 ret = audio_route_reset_and_update_path(adev->audio_route, paths); 146 if(ret) { 147 ALOGE("%s: audio_route_reset_and_update_path return %d\n", __func__, ret); 148 return ret; 149 } 150 } 151 return 0; 152 } 153 154 static int tfa_98xx_set_audio_mode(int enable, struct audio_device *adev, exTfa98xx_audio_mode_t audio_mode) 155 { 156 char paths[32] = "init_smart_pa"; 157 158 switch(audio_mode) { 159 case Audio_Mode_Music_Normal: 160 strcat(paths, " music"); 161 break; 162 case Audio_Mode_Voice: 163 case Audio_Mode_Hfp_Client: 164 case Audio_Mode_Hs_Hfp: 165 strcat(paths, " voice"); 166 break; 167 default: 168 ALOGE("%s: function %d not support!\n",__func__, audio_mode); 169 return -EINVAL; 170 } 171 172 ALOGV("%s: mixer paths is: %s, enable: %d\n", __func__, paths, enable); 173 adev_i2s_clock_operation(enable, adev, paths); 174 return 0; 175 176 } 177 178 static exTfa98xx_audio_mode_t tfa_98xx_get_audio_mode(struct speaker_data *data) 179 { 180 exTfa98xx_audio_mode_t tfa_98xx_audio_mode = Audio_Mode_None; 181 struct listnode *node; 182 struct audio_usecase *usecase; 183 audio_mode_t mode = data->adev->mode; 184 int i = 0; 185 186 ALOGV("%s: enter\n", __func__); 187 188 for (i = 0; i < Audio_Mode_Max; i++) 189 data->route_cnt[i] = 0; 190 191 list_for_each(node, &data->adev->usecase_list) { 192 usecase = node_to_item(node, struct audio_usecase, list); 193 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO) { 194 if(data->adev->snd_dev_ref_cnt[usecase->out_snd_device] != 0) { 195 tfa_98xx_audio_mode = Audio_Mode_Hs_Hfp; 196 data->route_cnt[tfa_98xx_audio_mode]++; 197 ALOGV("%s: audio_mode hs_hfp\n", __func__); 198 } 199 } else if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER) { 200 if ((mode == AUDIO_MODE_IN_CALL) || audio_extn_hfp_is_active(data->adev)) { 201 if (audio_extn_hfp_is_active(data->adev)) { 202 if(data->adev->snd_dev_ref_cnt[usecase->out_snd_device] != 0) { 203 tfa_98xx_audio_mode = Audio_Mode_Hfp_Client; 204 data->route_cnt[tfa_98xx_audio_mode]++; 205 ALOGV("%s: audio_mode hfp client\n", __func__); 206 } 207 } else { 208 if(data->adev->snd_dev_ref_cnt[usecase->out_snd_device] != 0) { 209 tfa_98xx_audio_mode = Audio_Mode_Voice; 210 data->route_cnt[tfa_98xx_audio_mode]++; 211 ALOGV("%s: audio_mode voice\n", __func__); 212 } 213 } 214 } else { 215 if (data->adev->snd_dev_ref_cnt[usecase->out_snd_device] != 0) { 216 tfa_98xx_audio_mode = Audio_Mode_Music_Normal; 217 data->route_cnt[tfa_98xx_audio_mode]++; 218 ALOGV("%s: tfa_98xx_audio_mode music\n", __func__); 219 } 220 } 221 } else { 222 ALOGE("%s: no device match \n", __func__); 223 } 224 } 225 ALOGV("%s: tfa_98xx_audio_mode %d exit\n", __func__, tfa_98xx_audio_mode); 226 227 return tfa_98xx_audio_mode; 228 } 229 230 static int tfa_98xx_set_func_mode(int enable, struct audio_device *adev, exTfa98xx_func_mode_t func_mode) 231 { 232 struct speaker_data *data = tfa98xx_speaker_data; 233 char paths[32] = "init_smart_pa"; 234 235 if (data) { 236 switch(func_mode) { 237 case Func_Mode_Speaker: 238 strcat(paths, " func_speaker"); 239 break; 240 case Func_Mode_BT: 241 strcat(paths, " func_bt"); 242 break; 243 default: 244 ALOGE("%s: function %d not support!\n",__func__, func_mode); 245 return -EINVAL; 246 } 247 248 ALOGV("%s: mixer paths is: %s, enable: %d\n", __func__, paths, enable); 249 adev_i2s_clock_operation(enable, adev, paths); 250 } 251 return 0; 252 } 253 254 static exTfa98xx_func_mode_t tfa_98xx_get_func_mode(exTfa98xx_audio_mode_t audio_mode) 255 { 256 exTfa98xx_func_mode_t func_mode = Func_Mode_None; 257 258 switch(audio_mode) { 259 case Audio_Mode_Music_Normal: 260 case Audio_Mode_Voice: 261 ALOGV("%s: tfa_98xx_func_mode speaker \n", __func__); 262 func_mode = Func_Mode_Speaker; 263 break; 264 case Audio_Mode_Hfp_Client: 265 case Audio_Mode_Hs_Hfp: 266 ALOGV("%s: tfa_98xx_func_mode bt \n", __func__); 267 func_mode = Func_Mode_BT; 268 break; 269 default: 270 break; 271 } 272 return func_mode; 273 } 274 275 static void tfa_98xx_disable_speaker(void) 276 { 277 struct speaker_data *data = tfa98xx_speaker_data; 278 int ret = 0; 279 280 ret = data->set_speaker_off(); 281 if (ret) { 282 ALOGE("%s: exTfa98xx_speakeroff failed result = %d\n", __func__, ret); 283 goto on_error; 284 } 285 286 ret = tfa_98xx_set_audio_mode(I2S_CLOCK_DISABLE, data->adev, current_audio_mode); 287 if (ret) { 288 ALOGE("%s: tfa_98xx_set_audio_mode disable failed return %d\n", __func__, ret); 289 goto on_error; 290 } 291 current_audio_mode = Audio_Mode_None; 292 on_error: 293 return; 294 295 } 296 297 298 void audio_extn_tfa_98xx_disable_speaker(snd_device_t snd_device) 299 { 300 struct speaker_data *data = tfa98xx_speaker_data; 301 int i = 0; 302 exTfa98xx_audio_mode_t new_audio_mode = Audio_Mode_None; 303 304 ALOGV("%s: enter\n", __func__); 305 306 if (data) { 307 if ((current_audio_mode == Audio_Mode_None) || (snd_device > SND_DEVICE_OUT_END)) 308 goto on_exit; 309 310 switch(snd_device) { 311 case SND_DEVICE_OUT_SPEAKER: 312 new_audio_mode = Audio_Mode_Music_Normal; 313 break; 314 case SND_DEVICE_OUT_VOICE_SPEAKER: 315 new_audio_mode = Audio_Mode_Voice; 316 break; 317 case SND_DEVICE_OUT_VOICE_SPEAKER_HFP: 318 new_audio_mode = Audio_Mode_Hfp_Client; 319 break; 320 case SND_DEVICE_OUT_BT_SCO: 321 new_audio_mode = Audio_Mode_Hs_Hfp; 322 break; 323 default: 324 break; 325 } 326 327 if ((new_audio_mode == Audio_Mode_None) || (data->ref_cnt[new_audio_mode] <= 0)) { 328 ALOGE("%s: device ref cnt is already 0", __func__); 329 goto on_exit; 330 } 331 332 data->ref_cnt[new_audio_mode]--; 333 334 for (i = 0; i < Audio_Mode_Max; i++) { 335 if (data->ref_cnt[i] > 0) { 336 ALOGD("%s: exTfa98xx_speaker still in use\n", __func__); 337 goto on_exit; 338 } 339 } 340 341 if (data->adev->enable_hfp) 342 data->set_speaker_volume_step(0, 0); 343 344 tfa_98xx_disable_speaker(); 345 } 346 347 ALOGV("%s: exit\n", __func__); 348 on_exit: 349 return; 350 } 351 352 int audio_extn_tfa_98xx_enable_speaker(void) 353 { 354 struct speaker_data *data = tfa98xx_speaker_data; 355 exTfa98xx_audio_mode_t new_audio_mode = Audio_Mode_Music_Normal; 356 int ret = 0; 357 int i = 0; 358 359 ALOGV("%s: enter\n", __func__); 360 361 if (data) { 362 363 new_audio_mode = tfa_98xx_get_audio_mode(data); 364 if ((new_audio_mode != Audio_Mode_None) && (data->ref_cnt[new_audio_mode] >= 1)) { 365 ALOGD("%s, mode %d already active!", __func__, new_audio_mode); 366 data->ref_cnt[new_audio_mode]++; 367 goto on_exit; 368 } 369 370 ret = tfa_98xx_set_audio_mode(I2S_CLOCK_ENABLE, data->adev, new_audio_mode); 371 if (ret) { 372 ALOGE("%s: tfa_98xx_set_audio_mode enable failed return %d\n", __func__, ret); 373 goto on_exit; 374 } 375 376 ret = data->set_speaker_on(new_audio_mode); 377 if (ret) { 378 ALOGE("%s: exTfa98xx_speakeron failed result = %d\n", __func__, ret); 379 goto on_exit; 380 } 381 382 current_audio_mode = new_audio_mode; 383 for (i = 0; i < Audio_Mode_Max; i++) { 384 data->ref_cnt[i] = data->route_cnt[i]; 385 } 386 data->update_ref_cnt = false; 387 } 388 389 ALOGV("%s: exit\n", __func__); 390 391 on_exit: 392 return ret; 393 394 } 395 396 void audio_extn_tfa_98xx_set_mode(void) 397 { 398 int ret = 0; 399 struct speaker_data *data = tfa98xx_speaker_data; 400 exTfa98xx_audio_mode_t new_audio_mode = Audio_Mode_None; 401 exTfa98xx_func_mode_t new_func_mode = Func_Mode_None; 402 403 ALOGV("%s: enter\n", __func__); 404 405 if (data) { 406 new_audio_mode = tfa_98xx_get_audio_mode(data); 407 408 new_func_mode = tfa_98xx_get_func_mode(new_audio_mode); 409 if (new_func_mode == Func_Mode_None) 410 return; 411 412 ret = tfa_98xx_set_func_mode(I2S_CLOCK_ENABLE, data->adev, new_func_mode); 413 if (ret) { 414 ALOGE("%s: tfa_98xx_set_func_mode enable return %d\n", __func__, ret); 415 } 416 data->update_ref_cnt = true; 417 } 418 419 ALOGV("%s: exit\n", __func__); 420 } 421 422 void audio_extn_tfa_98xx_set_mode_bt(void) 423 { 424 struct speaker_data *data = tfa98xx_speaker_data; 425 int ret = 0; 426 427 if (data) { 428 ret = tfa_98xx_set_func_mode(I2S_CLOCK_ENABLE, data->adev, Func_Mode_BT); 429 if (ret) { 430 ALOGE("%s: tfa_98xx_set_func_mode enable return %d\n", __func__, ret); 431 } 432 } 433 } 434 435 void audio_extn_tfa_98xx_update(void) 436 { 437 struct speaker_data *data = tfa98xx_speaker_data; 438 exTfa98xx_audio_mode_t new_audio_mode = Audio_Mode_Music_Normal; 439 440 ALOGD("%s: enter\n", __func__); 441 442 if (data) { 443 444 new_audio_mode = tfa_98xx_get_audio_mode(data); 445 if (new_audio_mode <= current_audio_mode) { 446 ALOGE("%s: audio_extn_tfa_98xx_update same mode\n", __func__); 447 if (data->update_ref_cnt == true) { 448 data->ref_cnt[new_audio_mode]++; 449 data->update_ref_cnt = false; 450 } 451 goto on_error; 452 } 453 454 if (current_audio_mode != Audio_Mode_None) { 455 tfa_98xx_disable_speaker(); 456 } 457 458 audio_extn_tfa_98xx_enable_speaker(); 459 460 } 461 462 ALOGV("%s: exit\n", __func__); 463 on_error: 464 return; 465 466 } 467 468 void audio_extn_tfa_98xx_set_voice_vol(float vol) 469 { 470 struct speaker_data *data = tfa98xx_speaker_data; 471 int vsteps = 0; 472 473 if (data) { 474 if (data->adev->enable_hfp) { 475 if (vol < 0.0) { 476 vol = 0.0; 477 } else { 478 vol = ((vol > HFP_MAX_VOLUME) ? 1.0 : (vol / HFP_MAX_VOLUME)); 479 } 480 vsteps = (int)floorf((1.0 - vol) * TFA_98XX_HFP_VSETPS); 481 } else { 482 return; 483 } 484 ALOGD("%s: vsteps %d\n", __func__, vsteps); 485 data->set_speaker_volume_step(vsteps, vsteps); 486 } 487 } 488 489 bool audio_extn_tfa_98xx_is_supported(void) 490 { 491 struct speaker_data *data = tfa98xx_speaker_data; 492 if (data) 493 return true; 494 else 495 return false; 496 } 497 498 int audio_extn_tfa_98xx_init(struct audio_device *adev) 499 { 500 int ret = 0; 501 struct speaker_data *data = open_speaker_bundle(); 502 503 ALOGV("%s: enter\n", __func__); 504 505 if (data) { 506 ret = tfa_98xx_set_audio_mode(I2S_CLOCK_ENABLE, adev, Audio_Mode_Music_Normal); 507 if (ret) { 508 ALOGE("%s: tfa_98xx_set_audio_mode enable return %d\n", __func__, ret); 509 goto err_init; 510 } 511 512 ret = data->set_speaker_calibration(0); 513 if (ret) { 514 ALOGE("%s: exTfa98xx_calibration return %d\n", __func__, ret); 515 } 516 517 ret = tfa_98xx_set_audio_mode(I2S_CLOCK_DISABLE, adev, Audio_Mode_Music_Normal); 518 if (ret) { 519 ALOGE("%s: tfa_98xx_set_audio_mode disable return %d\n", __func__, ret); 520 goto err_init; 521 } 522 523 data->adev = adev; 524 tfa98xx_speaker_data = data; 525 ALOGV("%s: exit\n", __func__); 526 return 0; 527 528 } 529 530 err_init: 531 close_speaker_bundle(data); 532 return -EINVAL; 533 } 534 535 void audio_extn_tfa_98xx_deinit(void) 536 { 537 struct speaker_data *data = tfa98xx_speaker_data; 538 539 if (data) { 540 data->set_speaker_off(); 541 close_speaker_bundle(data); 542 tfa98xx_speaker_data = NULL; 543 } 544 } 545 546