1 /* 2 * Copyright (C) 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 "audio_hw_utils" 18 //#define LOG_NDEBUG 0 19 20 #include <errno.h> 21 #include <cutils/properties.h> 22 #include <cutils/config_utils.h> 23 #include <stdlib.h> 24 #include <dlfcn.h> 25 #include <unistd.h> 26 #include <cutils/str_parms.h> 27 #include <log/log.h> 28 #include <cutils/misc.h> 29 30 #include "acdb.h" 31 #include "audio_hw.h" 32 #include "platform.h" 33 #include "platform_api.h" 34 #include "audio_extn.h" 35 36 #define MAX_LENGTH_MIXER_CONTROL_IN_INT 128 37 38 static int set_stream_app_type_mixer_ctrl(struct audio_device *adev, 39 int pcm_device_id, int app_type, 40 int acdb_dev_id, int sample_rate, 41 int stream_type, 42 snd_device_t snd_device) 43 { 44 45 char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT]; 46 struct mixer_ctl *ctl; 47 int app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT], len = 0, rc = 0; 48 int snd_device_be_idx = -1; 49 50 if (stream_type == PCM_PLAYBACK) { 51 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), 52 "Audio Stream %d App Type Cfg", pcm_device_id); 53 } else if (stream_type == PCM_CAPTURE) { 54 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), 55 "Audio Stream Capture %d App Type Cfg", pcm_device_id); 56 } 57 58 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name); 59 if (!ctl) { 60 ALOGE("%s: Could not get ctl for mixer cmd - %s", 61 __func__, mixer_ctl_name); 62 rc = -EINVAL; 63 goto exit; 64 } 65 app_type_cfg[len++] = app_type; 66 app_type_cfg[len++] = acdb_dev_id; 67 app_type_cfg[len++] = sample_rate; 68 69 snd_device_be_idx = platform_get_snd_device_backend_index(snd_device); 70 if (snd_device_be_idx > 0) 71 app_type_cfg[len++] = snd_device_be_idx; 72 ALOGV("%s: stream type %d app_type %d, acdb_dev_id %d " 73 "sample rate %d, snd_device_be_idx %d", 74 __func__, stream_type, app_type, acdb_dev_id, sample_rate, 75 snd_device_be_idx); 76 mixer_ctl_set_array(ctl, app_type_cfg, len); 77 78 exit: 79 return rc; 80 } 81 82 void audio_extn_utils_send_default_app_type_cfg(void *platform, struct mixer *mixer) 83 { 84 int app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {-1}; 85 int length = 0, app_type = 0,rc = 0; 86 struct mixer_ctl *ctl = NULL; 87 const char *mixer_ctl_name = "App Type Config"; 88 89 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name); 90 if (!ctl) { 91 ALOGE("%s: Could not get ctl for mixer cmd - %s",__func__, mixer_ctl_name); 92 return; 93 } 94 rc = platform_get_default_app_type_v2(platform, PCM_PLAYBACK, &app_type); 95 if (rc == 0) { 96 app_type_cfg[length++] = 1; 97 app_type_cfg[length++] = app_type; 98 app_type_cfg[length++] = 48000; 99 app_type_cfg[length++] = 16; 100 mixer_ctl_set_array(ctl, app_type_cfg, length); 101 } 102 return; 103 } 104 105 static const char *flags_to_mode(int dir, uint32_t flags) 106 { 107 if (dir == 0) { 108 if (flags & AUDIO_OUTPUT_FLAG_VOIP_RX) { 109 return "voip"; 110 } 111 } else if (dir == 1) { 112 if (flags & AUDIO_INPUT_FLAG_VOIP_TX) { 113 return "voip"; 114 } 115 } 116 return "default"; 117 } 118 119 static int audio_extn_utils_send_app_type_cfg_hfp(struct audio_device *adev, 120 struct audio_usecase *usecase) 121 { 122 struct mixer_ctl *ctl; 123 int pcm_device_id, acdb_dev_id = 0, snd_device = usecase->out_snd_device; 124 int32_t sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE; 125 int app_type = 0, rc = 0; 126 127 ALOGV("%s", __func__); 128 129 if (usecase->type != PCM_HFP_CALL) { 130 ALOGV("%s: not a playback or HFP path, no need to cfg app type", __func__); 131 rc = 0; 132 goto exit_send_app_type_cfg; 133 } 134 if ((usecase->id != USECASE_AUDIO_HFP_SCO) && 135 (usecase->id != USECASE_AUDIO_HFP_SCO_WB)) { 136 ALOGV("%s: a playback path where app type cfg is not required", __func__); 137 rc = 0; 138 goto exit_send_app_type_cfg; 139 } 140 141 snd_device = usecase->out_snd_device; 142 pcm_device_id = platform_get_pcm_device_id(usecase->id, PCM_PLAYBACK); 143 144 acdb_dev_id = platform_get_snd_device_acdb_id(snd_device); 145 if (acdb_dev_id < 0) { 146 ALOGE("%s: Couldn't get the acdb dev id", __func__); 147 rc = -EINVAL; 148 goto exit_send_app_type_cfg; 149 } 150 151 if (usecase->type == PCM_HFP_CALL) { 152 153 /* config HFP session:1 playback path */ 154 rc = platform_get_default_app_type_v2(adev->platform, PCM_PLAYBACK, &app_type); 155 if (rc < 0) 156 goto exit_send_app_type_cfg; 157 158 sample_rate= CODEC_BACKEND_DEFAULT_SAMPLE_RATE; 159 rc = set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type, 160 acdb_dev_id, sample_rate, 161 PCM_PLAYBACK, 162 SND_DEVICE_NONE); // use legacy behavior 163 if (rc < 0) 164 goto exit_send_app_type_cfg; 165 /* config HFP session:1 capture path */ 166 rc = platform_get_default_app_type_v2(adev->platform, PCM_CAPTURE, &app_type); 167 168 if (rc == 0) { 169 rc = set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type, 170 acdb_dev_id, sample_rate, 171 PCM_CAPTURE, 172 SND_DEVICE_NONE); 173 if (rc < 0) 174 goto exit_send_app_type_cfg; 175 } 176 /* config HFP session:2 capture path */ 177 pcm_device_id = HFP_ASM_RX_TX; 178 snd_device = usecase->in_snd_device; 179 acdb_dev_id = platform_get_snd_device_acdb_id(snd_device); 180 if (acdb_dev_id <= 0) { 181 ALOGE("%s: Couldn't get the acdb dev id", __func__); 182 rc = -EINVAL; 183 goto exit_send_app_type_cfg; 184 } 185 rc = platform_get_default_app_type_v2(adev->platform, PCM_CAPTURE, &app_type); 186 if (rc == 0) { 187 rc = set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type, 188 acdb_dev_id, sample_rate, PCM_CAPTURE, 189 SND_DEVICE_NONE); 190 if (rc < 0) 191 goto exit_send_app_type_cfg; 192 } 193 194 /* config HFP session:2 playback path */ 195 rc = platform_get_default_app_type_v2(adev->platform, PCM_PLAYBACK, &app_type); 196 if (rc == 0) { 197 rc = set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type, 198 acdb_dev_id, sample_rate, 199 PCM_PLAYBACK, SND_DEVICE_NONE); 200 if (rc < 0) 201 goto exit_send_app_type_cfg; 202 } 203 } 204 205 rc = 0; 206 exit_send_app_type_cfg: 207 return rc; 208 } 209 210 211 static int derive_capture_app_type_cfg(struct audio_device *adev, 212 struct audio_usecase *usecase, 213 int *app_type, 214 int *sample_rate) 215 { 216 if (usecase->stream.in == NULL) { 217 return -1; 218 } 219 struct stream_in *in = usecase->stream.in; 220 struct stream_app_type_cfg *app_type_cfg = &in->app_type_cfg; 221 222 *sample_rate = DEFAULT_INPUT_SAMPLING_RATE; 223 if (audio_is_usb_in_device(in->device)) { 224 platform_check_and_update_copp_sample_rate(adev->platform, 225 usecase->in_snd_device, 226 in->sample_rate, 227 sample_rate); 228 } 229 230 app_type_cfg->mode = flags_to_mode(1 /*capture*/, in->flags); 231 ALOGV("%s mode %s", __func__, app_type_cfg->mode); 232 if (in->format == AUDIO_FORMAT_PCM_16_BIT) { 233 platform_get_app_type_v2(adev->platform, 234 PCM_CAPTURE, 235 app_type_cfg->mode, 236 16, 237 app_type_cfg->sample_rate, 238 app_type); 239 } else if (in->format == AUDIO_FORMAT_PCM_24_BIT_PACKED || 240 in->format == AUDIO_FORMAT_PCM_8_24_BIT) { 241 platform_get_app_type_v2(adev->platform, 242 PCM_CAPTURE, 243 app_type_cfg->mode, 244 24, 245 app_type_cfg->sample_rate, 246 app_type); 247 } else if (in->format == AUDIO_FORMAT_PCM_32_BIT) { 248 platform_get_app_type_v2(adev->platform, 249 PCM_CAPTURE, 250 app_type_cfg->mode, 251 32, 252 app_type_cfg->sample_rate, 253 app_type); 254 } else { 255 ALOGE("%s bad format\n", __func__); 256 return -1; 257 } 258 259 app_type_cfg->app_type = *app_type; 260 app_type_cfg->sample_rate = *sample_rate; 261 return 0; 262 } 263 264 static int derive_playback_app_type_cfg(struct audio_device *adev, 265 struct audio_usecase *usecase, 266 int *app_type, 267 int *sample_rate) 268 { 269 if (usecase->stream.out == NULL) { 270 return -1; 271 } 272 struct stream_out *out = usecase->stream.out; 273 struct stream_app_type_cfg *app_type_cfg = &out->app_type_cfg; 274 275 *sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE; 276 277 // add speaker prot changes if needed 278 // and use that to check for device 279 if (audio_is_usb_out_device(out->devices)) { 280 platform_check_and_update_copp_sample_rate(adev->platform, 281 usecase->out_snd_device, 282 out->sample_rate, 283 sample_rate); 284 } else if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) { 285 audio_extn_a2dp_get_sample_rate(sample_rate); 286 ALOGI("%s: Using sample rate %d for A2DP CoPP", __func__, 287 *sample_rate); 288 } 289 290 app_type_cfg->mode = flags_to_mode(0 /*playback*/, out->flags); 291 if (!audio_is_linear_pcm(out->format)) { 292 platform_get_app_type_v2(adev->platform, 293 PCM_PLAYBACK, 294 app_type_cfg->mode, 295 24, 296 *sample_rate, 297 app_type); 298 ALOGV("Non pcm got app type %d", *app_type); 299 } else if (out->format == AUDIO_FORMAT_PCM_16_BIT) { 300 platform_get_app_type_v2(adev->platform, 301 PCM_PLAYBACK, 302 app_type_cfg->mode, 303 16, 304 *sample_rate, 305 app_type); 306 } else if (out->format == AUDIO_FORMAT_PCM_24_BIT_PACKED || 307 out->format == AUDIO_FORMAT_PCM_8_24_BIT) { 308 platform_get_app_type_v2(adev->platform, 309 PCM_PLAYBACK, 310 app_type_cfg->mode, 311 24, 312 *sample_rate, 313 app_type); 314 } else if (out->format == AUDIO_FORMAT_PCM_32_BIT) { 315 platform_get_app_type_v2(adev->platform, 316 PCM_PLAYBACK, 317 app_type_cfg->mode, 318 32, 319 *sample_rate, 320 app_type); 321 } else { 322 ALOGE("%s bad format\n", __func__); 323 return -1; 324 } 325 326 app_type_cfg->app_type = *app_type; 327 app_type_cfg->sample_rate = *sample_rate; 328 return 0; 329 } 330 331 static int derive_acdb_dev_id(struct audio_device *adev __unused, 332 struct audio_usecase *usecase) 333 { 334 struct stream_out *out; 335 struct stream_in *in; 336 337 if (usecase->type == PCM_PLAYBACK) { 338 return platform_get_snd_device_acdb_id(usecase->out_snd_device); 339 } else if(usecase->type == PCM_CAPTURE) { 340 return platform_get_snd_device_acdb_id(usecase->in_snd_device); 341 } 342 return -1; 343 } 344 345 int audio_extn_utils_send_app_type_cfg(struct audio_device *adev, 346 struct audio_usecase *usecase) 347 { 348 int len = 0; 349 int sample_rate; 350 int app_type; 351 int acdb_dev_id; 352 int new_snd_device[2] = {0}; 353 int i = 0, num_devices = 1; 354 size_t app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0}; 355 char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0}; 356 int pcm_device_id; 357 struct mixer_ctl *ctl; 358 int ret; 359 360 if (usecase->type == PCM_HFP_CALL) { 361 return audio_extn_utils_send_app_type_cfg_hfp(adev, usecase); 362 } 363 364 if (!platform_supports_app_type_cfg()) 365 return -1; 366 367 if (usecase->type == PCM_PLAYBACK) { 368 ret = derive_playback_app_type_cfg(adev, 369 usecase, 370 &app_type, 371 &sample_rate); 372 } else if (usecase->type == PCM_CAPTURE) { 373 ret = derive_capture_app_type_cfg(adev, 374 usecase, 375 &app_type, 376 &sample_rate); 377 } else { 378 ALOGE("%s: Invalid uc type : 0x%x", __func__, usecase->type); 379 return -1; 380 } 381 382 if (ret < 0) { 383 ALOGE("%s: Failed to derive app_type for uc type : 0x%x", __func__, 384 usecase->type); 385 return -1; 386 } 387 388 if (usecase->type == PCM_PLAYBACK) { 389 if (platform_can_split_snd_device(usecase->out_snd_device, 390 &num_devices, new_snd_device) < 0) 391 new_snd_device[0] = usecase->out_snd_device; 392 393 } else if (usecase->type == PCM_CAPTURE) 394 new_snd_device[0] = usecase->in_snd_device; 395 396 pcm_device_id = platform_get_pcm_device_id(usecase->id, usecase->type); 397 398 for (i = 0; i < num_devices; i++) { 399 acdb_dev_id = platform_get_snd_device_acdb_id(new_snd_device[i]); 400 401 if (acdb_dev_id < 0) { 402 ALOGE("%s: Could not find acdb id for device(%d)", 403 __func__, new_snd_device[i]); 404 return -EINVAL; 405 } 406 ALOGV("%s: sending app type for snd_device(%d) acdb_id(%d) i %d", 407 __func__, new_snd_device[i], acdb_dev_id, i); 408 409 set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type, acdb_dev_id, 410 sample_rate, 411 usecase->type, 412 new_snd_device[i]); 413 } 414 415 return 0; 416 } 417 418 int audio_extn_utils_send_app_type_gain(struct audio_device *adev, 419 int app_type, 420 int *gain) 421 { 422 int gain_cfg[4]; 423 const char *mixer_ctl_name = "App Type Gain"; 424 struct mixer_ctl *ctl; 425 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name); 426 if (!ctl) { 427 ALOGE("%s: Could not get volume ctl mixer %s", __func__, 428 mixer_ctl_name); 429 return -EINVAL; 430 } 431 gain_cfg[0] = 0; 432 gain_cfg[1] = app_type; 433 gain_cfg[2] = gain[0]; 434 gain_cfg[3] = gain[1]; 435 ALOGV("%s app_type %d l(%d) r(%d)", __func__, app_type, gain[0], gain[1]); 436 return mixer_ctl_set_array(ctl, gain_cfg, 437 sizeof(gain_cfg)/sizeof(gain_cfg[0])); 438 } 439 440 // this assumes correct app_type and sample_rate fields 441 // have been set for the stream using audio_extn_utils_send_app_type_cfg 442 void audio_extn_utils_send_audio_calibration(struct audio_device *adev, 443 struct audio_usecase *usecase) 444 { 445 int type = usecase->type; 446 int app_type = 0; 447 448 if (type == PCM_PLAYBACK && usecase->stream.out != NULL) { 449 struct stream_out *out = usecase->stream.out; 450 ALOGV("%s send cal for app_type %d, rate %d", __func__, 451 out->app_type_cfg.app_type, 452 out->app_type_cfg.sample_rate); 453 platform_send_audio_calibration_v2(adev->platform, usecase, 454 out->app_type_cfg.app_type, 455 out->app_type_cfg.sample_rate); 456 } else if (type == PCM_CAPTURE && usecase->stream.in != NULL) { 457 struct stream_in *in = usecase->stream.in; 458 ALOGV("%s send cal for capture app_type %d, rate %d", __func__, 459 in->app_type_cfg.app_type, 460 in->app_type_cfg.sample_rate); 461 platform_send_audio_calibration_v2(adev->platform, usecase, 462 in->app_type_cfg.app_type, 463 in->app_type_cfg.sample_rate); 464 } else { 465 /* when app type is default. the sample rate is not used to send cal */ 466 platform_get_default_app_type_v2(adev->platform, type, &app_type); 467 platform_send_audio_calibration_v2(adev->platform, usecase, app_type, 468 48000); 469 } 470 } 471 472 #define MAX_SND_CARD 8 473 #define RETRY_US 500000 474 #define RETRY_NUMBER 10 475 476 #define min(a, b) ((a) < (b) ? (a) : (b)) 477 478 static const char *kConfigLocationList[] = 479 {"/odm/etc", "/vendor/etc", "/system/etc"}; 480 static const int kConfigLocationListSize = 481 (sizeof(kConfigLocationList) / sizeof(kConfigLocationList[0])); 482 483 bool audio_extn_utils_resolve_config_file(char file_name[MIXER_PATH_MAX_LENGTH]) 484 { 485 char full_config_path[MIXER_PATH_MAX_LENGTH]; 486 for (int i = 0; i < kConfigLocationListSize; i++) { 487 snprintf(full_config_path, 488 MIXER_PATH_MAX_LENGTH, 489 "%s/%s", 490 kConfigLocationList[i], 491 file_name); 492 if (F_OK == access(full_config_path, 0)) { 493 strcpy(file_name, full_config_path); 494 return true; 495 } 496 } 497 return false; 498 } 499 500 /* platform_info_file should be size 'MIXER_PATH_MAX_LENGTH' */ 501 int audio_extn_utils_get_platform_info(const char* snd_card_name, char* platform_info_file) 502 { 503 if (NULL == snd_card_name) { 504 return -1; 505 } 506 507 struct snd_card_split *snd_split_handle = NULL; 508 int ret = 0; 509 audio_extn_set_snd_card_split(snd_card_name); 510 snd_split_handle = audio_extn_get_snd_card_split(); 511 512 snprintf(platform_info_file, MIXER_PATH_MAX_LENGTH, "%s_%s_%s.xml", 513 PLATFORM_INFO_XML_BASE_STRING, snd_split_handle->snd_card, 514 snd_split_handle->form_factor); 515 516 if (!audio_extn_utils_resolve_config_file(platform_info_file)) { 517 memset(platform_info_file, 0, MIXER_PATH_MAX_LENGTH); 518 snprintf(platform_info_file, MIXER_PATH_MAX_LENGTH, "%s_%s.xml", 519 PLATFORM_INFO_XML_BASE_STRING, snd_split_handle->snd_card); 520 521 if (!audio_extn_utils_resolve_config_file(platform_info_file)) { 522 memset(platform_info_file, 0, MIXER_PATH_MAX_LENGTH); 523 strlcpy(platform_info_file, PLATFORM_INFO_XML_PATH, MIXER_PATH_MAX_LENGTH); 524 ret = audio_extn_utils_resolve_config_file(platform_info_file) ? 0 : -1; 525 } 526 } 527 528 return ret; 529 } 530 531 int audio_extn_utils_get_snd_card_num() 532 { 533 534 void *hw_info = NULL; 535 struct mixer *mixer = NULL; 536 int retry_num = 0; 537 int snd_card_num = 0; 538 const char* snd_card_name = NULL; 539 char platform_info_file[MIXER_PATH_MAX_LENGTH]= {0}; 540 541 struct acdb_platform_data *my_data = calloc(1, sizeof(struct acdb_platform_data)); 542 543 bool card_verifed[MAX_SND_CARD] = {0}; 544 const int retry_limit = property_get_int32("audio.snd_card.open.retries", RETRY_NUMBER); 545 546 for (;;) { 547 if (snd_card_num >= MAX_SND_CARD) { 548 if (retry_num++ >= retry_limit) { 549 ALOGE("%s: Unable to find correct sound card, aborting.", __func__); 550 snd_card_num = -1; 551 goto done; 552 } 553 554 snd_card_num = 0; 555 usleep(RETRY_US); 556 continue; 557 } 558 559 if (card_verifed[snd_card_num]) { 560 ++snd_card_num; 561 continue; 562 } 563 564 mixer = mixer_open(snd_card_num); 565 566 if (!mixer) { 567 ALOGE("%s: Unable to open the mixer card: %d", __func__, 568 snd_card_num); 569 ++snd_card_num; 570 continue; 571 } 572 573 card_verifed[snd_card_num] = true; 574 575 snd_card_name = mixer_get_name(mixer); 576 hw_info = hw_info_init(snd_card_name); 577 578 if (audio_extn_utils_get_platform_info(snd_card_name, platform_info_file) < 0) { 579 ALOGE("Failed to find platform_info_file"); 580 goto cleanup; 581 } 582 583 /* Initialize snd card name specific ids and/or backends*/ 584 if (platform_info_init(platform_info_file, my_data, false, 585 &acdb_set_parameters) < 0) { 586 ALOGE("Failed to find platform_info_file"); 587 goto cleanup; 588 } 589 590 /* validate the sound card name 591 * my_data->snd_card_name can contain 592 * <a> complete sound card name, i.e. <device>-<codec>-<form_factor>-snd-card 593 * example: msm8994-tomtom-mtp-snd-card 594 * <b> or sub string of the card name, i.e. <device>-<codec> 595 * example: msm8994-tomtom 596 * snd_card_name is truncated to 32 charaters as per mixer_get_name() implementation 597 * so use min of my_data->snd_card_name and snd_card_name length for comparison 598 */ 599 600 if (my_data->snd_card_name != NULL && 601 strncmp(snd_card_name, my_data->snd_card_name, 602 min(strlen(snd_card_name), strlen(my_data->snd_card_name))) != 0) { 603 ALOGI("%s: found valid sound card %s, but not primary sound card %s", 604 __func__, snd_card_name, my_data->snd_card_name); 605 goto cleanup; 606 } 607 608 ALOGI("%s: found sound card %s, primary sound card expected is %s", 609 __func__, snd_card_name, my_data->snd_card_name); 610 break; 611 cleanup: 612 ++snd_card_num; 613 mixer_close(mixer); 614 mixer = NULL; 615 hw_info_deinit(hw_info); 616 hw_info = NULL; 617 } 618 619 done: 620 mixer_close(mixer); 621 hw_info_deinit(hw_info); 622 623 if (my_data) 624 free(my_data); 625 626 return snd_card_num; 627 } 628