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 } 285 286 app_type_cfg->mode = flags_to_mode(0 /*playback*/, out->flags); 287 if (!audio_is_linear_pcm(out->format)) { 288 platform_get_app_type_v2(adev->platform, 289 PCM_PLAYBACK, 290 app_type_cfg->mode, 291 24, 292 *sample_rate, 293 app_type); 294 ALOGV("Non pcm got app type %d", *app_type); 295 } else if (out->format == AUDIO_FORMAT_PCM_16_BIT) { 296 platform_get_app_type_v2(adev->platform, 297 PCM_PLAYBACK, 298 app_type_cfg->mode, 299 16, 300 *sample_rate, 301 app_type); 302 } else if (out->format == AUDIO_FORMAT_PCM_24_BIT_PACKED || 303 out->format == AUDIO_FORMAT_PCM_8_24_BIT) { 304 platform_get_app_type_v2(adev->platform, 305 PCM_PLAYBACK, 306 app_type_cfg->mode, 307 24, 308 *sample_rate, 309 app_type); 310 } else if (out->format == AUDIO_FORMAT_PCM_32_BIT) { 311 platform_get_app_type_v2(adev->platform, 312 PCM_PLAYBACK, 313 app_type_cfg->mode, 314 32, 315 *sample_rate, 316 app_type); 317 } else { 318 ALOGE("%s bad format\n", __func__); 319 return -1; 320 } 321 322 app_type_cfg->app_type = *app_type; 323 app_type_cfg->sample_rate = *sample_rate; 324 return 0; 325 } 326 327 static int derive_acdb_dev_id(struct audio_device *adev __unused, 328 struct audio_usecase *usecase) 329 { 330 struct stream_out *out; 331 struct stream_in *in; 332 333 if (usecase->type == PCM_PLAYBACK) { 334 return platform_get_snd_device_acdb_id(usecase->out_snd_device); 335 } else if(usecase->type == PCM_CAPTURE) { 336 return platform_get_snd_device_acdb_id(usecase->in_snd_device); 337 } 338 return -1; 339 } 340 341 int audio_extn_utils_send_app_type_cfg(struct audio_device *adev, 342 struct audio_usecase *usecase) 343 { 344 int len = 0; 345 int sample_rate; 346 int app_type; 347 int acdb_dev_id; 348 size_t app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0}; 349 char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0}; 350 int pcm_device_id; 351 struct mixer_ctl *ctl; 352 int ret; 353 354 if (usecase->type == PCM_HFP_CALL) { 355 return audio_extn_utils_send_app_type_cfg_hfp(adev, usecase); 356 } 357 358 if (!platform_supports_app_type_cfg()) 359 return -1; 360 361 if (usecase->type == PCM_PLAYBACK) { 362 ret = derive_playback_app_type_cfg(adev, 363 usecase, 364 &app_type, 365 &sample_rate); 366 } else if (usecase->type == PCM_CAPTURE) { 367 ret = derive_capture_app_type_cfg(adev, 368 usecase, 369 &app_type, 370 &sample_rate); 371 } else { 372 ALOGE("%s: Invalid uc type : 0x%x", __func__, usecase->type); 373 return -1; 374 } 375 376 if (ret < 0) { 377 ALOGE("%s: Failed to derive app_type for uc type : 0x%x", __func__, 378 usecase->type); 379 return -1; 380 } 381 382 acdb_dev_id = derive_acdb_dev_id(adev, usecase); 383 if (acdb_dev_id <= 0) { 384 ALOGE("%s: Couldn't get the acdb dev id", __func__); 385 return -1; 386 } 387 388 pcm_device_id = platform_get_pcm_device_id(usecase->id, usecase->type); 389 set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type, acdb_dev_id, 390 sample_rate, 391 usecase->type, 392 usecase->type == PCM_PLAYBACK ? usecase->out_snd_device : 393 usecase->in_snd_device); 394 return 0; 395 } 396 397 int audio_extn_utils_send_app_type_gain(struct audio_device *adev, 398 int app_type, 399 int *gain) 400 { 401 int gain_cfg[4]; 402 const char *mixer_ctl_name = "App Type Gain"; 403 struct mixer_ctl *ctl; 404 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name); 405 if (!ctl) { 406 ALOGE("%s: Could not get volume ctl mixer %s", __func__, 407 mixer_ctl_name); 408 return -EINVAL; 409 } 410 gain_cfg[0] = 0; 411 gain_cfg[1] = app_type; 412 gain_cfg[2] = gain[0]; 413 gain_cfg[3] = gain[1]; 414 ALOGV("%s app_type %d l(%d) r(%d)", __func__, app_type, gain[0], gain[1]); 415 return mixer_ctl_set_array(ctl, gain_cfg, 416 sizeof(gain_cfg)/sizeof(gain_cfg[0])); 417 } 418 419 // this assumes correct app_type and sample_rate fields 420 // have been set for the stream using audio_extn_utils_send_app_type_cfg 421 void audio_extn_utils_send_audio_calibration(struct audio_device *adev, 422 struct audio_usecase *usecase) 423 { 424 int type = usecase->type; 425 int app_type = 0; 426 427 if (type == PCM_PLAYBACK && usecase->stream.out != NULL) { 428 struct stream_out *out = usecase->stream.out; 429 ALOGV("%s send cal for app_type %d, rate %d", __func__, 430 out->app_type_cfg.app_type, 431 out->app_type_cfg.sample_rate); 432 platform_send_audio_calibration_v2(adev->platform, usecase, 433 out->app_type_cfg.app_type, 434 out->app_type_cfg.sample_rate); 435 } else if (type == PCM_CAPTURE && usecase->stream.in != NULL) { 436 struct stream_in *in = usecase->stream.in; 437 ALOGV("%s send cal for capture app_type %d, rate %d", __func__, 438 in->app_type_cfg.app_type, 439 in->app_type_cfg.sample_rate); 440 platform_send_audio_calibration_v2(adev->platform, usecase, 441 in->app_type_cfg.app_type, 442 in->app_type_cfg.sample_rate); 443 } else { 444 /* when app type is default. the sample rate is not used to send cal */ 445 platform_get_default_app_type_v2(adev->platform, type, &app_type); 446 platform_send_audio_calibration_v2(adev->platform, usecase, app_type, 447 48000); 448 } 449 } 450 451 #define MAX_SND_CARD 8 452 #define RETRY_US 500000 453 #define RETRY_NUMBER 10 454 455 #define min(a, b) ((a) < (b) ? (a) : (b)) 456 457 static const char *kConfigLocationList[] = 458 {"/odm/etc", "/vendor/etc", "/system/etc"}; 459 static const int kConfigLocationListSize = 460 (sizeof(kConfigLocationList) / sizeof(kConfigLocationList[0])); 461 462 bool audio_extn_utils_resolve_config_file(char file_name[MIXER_PATH_MAX_LENGTH]) 463 { 464 char full_config_path[MIXER_PATH_MAX_LENGTH]; 465 for (int i = 0; i < kConfigLocationListSize; i++) { 466 snprintf(full_config_path, 467 MIXER_PATH_MAX_LENGTH, 468 "%s/%s", 469 kConfigLocationList[i], 470 file_name); 471 if (F_OK == access(full_config_path, 0)) { 472 strcpy(file_name, full_config_path); 473 return true; 474 } 475 } 476 return false; 477 } 478 479 /* platform_info_file should be size 'MIXER_PATH_MAX_LENGTH' */ 480 int audio_extn_utils_get_platform_info(const char* snd_card_name, char* platform_info_file) 481 { 482 if (NULL == snd_card_name) { 483 return -1; 484 } 485 486 struct snd_card_split *snd_split_handle = NULL; 487 int ret = 0; 488 audio_extn_set_snd_card_split(snd_card_name); 489 snd_split_handle = audio_extn_get_snd_card_split(); 490 491 snprintf(platform_info_file, MIXER_PATH_MAX_LENGTH, "%s_%s_%s.xml", 492 PLATFORM_INFO_XML_BASE_STRING, snd_split_handle->snd_card, 493 snd_split_handle->form_factor); 494 495 if (!audio_extn_utils_resolve_config_file(platform_info_file)) { 496 memset(platform_info_file, 0, MIXER_PATH_MAX_LENGTH); 497 snprintf(platform_info_file, MIXER_PATH_MAX_LENGTH, "%s_%s.xml", 498 PLATFORM_INFO_XML_BASE_STRING, snd_split_handle->snd_card); 499 500 if (!audio_extn_utils_resolve_config_file(platform_info_file)) { 501 memset(platform_info_file, 0, MIXER_PATH_MAX_LENGTH); 502 strlcpy(platform_info_file, PLATFORM_INFO_XML_PATH, MIXER_PATH_MAX_LENGTH); 503 ret = audio_extn_utils_resolve_config_file(platform_info_file) ? 0 : -1; 504 } 505 } 506 507 return ret; 508 } 509 510 int audio_extn_utils_get_snd_card_num() 511 { 512 513 void *hw_info = NULL; 514 struct mixer *mixer = NULL; 515 int retry_num = 0; 516 int snd_card_num = 0; 517 const char* snd_card_name = NULL; 518 char platform_info_file[MIXER_PATH_MAX_LENGTH]= {0}; 519 520 struct acdb_platform_data *my_data = calloc(1, sizeof(struct acdb_platform_data)); 521 522 bool card_verifed[MAX_SND_CARD] = {0}; 523 const int retry_limit = property_get_int32("audio.snd_card.open.retries", RETRY_NUMBER); 524 525 for (;;) { 526 if (snd_card_num >= MAX_SND_CARD) { 527 if (retry_num++ >= retry_limit) { 528 ALOGE("%s: Unable to find correct sound card, aborting.", __func__); 529 snd_card_num = -1; 530 goto done; 531 } 532 533 snd_card_num = 0; 534 usleep(RETRY_US); 535 continue; 536 } 537 538 if (card_verifed[snd_card_num]) { 539 ++snd_card_num; 540 continue; 541 } 542 543 mixer = mixer_open(snd_card_num); 544 545 if (!mixer) { 546 ALOGE("%s: Unable to open the mixer card: %d", __func__, 547 snd_card_num); 548 ++snd_card_num; 549 continue; 550 } 551 552 card_verifed[snd_card_num] = true; 553 554 snd_card_name = mixer_get_name(mixer); 555 hw_info = hw_info_init(snd_card_name); 556 557 if (audio_extn_utils_get_platform_info(snd_card_name, platform_info_file) < 0) { 558 ALOGE("Failed to find platform_info_file"); 559 goto cleanup; 560 } 561 562 /* Initialize snd card name specific ids and/or backends*/ 563 if (snd_card_info_init(platform_info_file, my_data, 564 &acdb_set_parameters) < 0) { 565 ALOGE("Failed to find platform_info_file"); 566 goto cleanup; 567 } 568 569 /* validate the sound card name 570 * my_data->snd_card_name can contain 571 * <a> complete sound card name, i.e. <device>-<codec>-<form_factor>-snd-card 572 * example: msm8994-tomtom-mtp-snd-card 573 * <b> or sub string of the card name, i.e. <device>-<codec> 574 * example: msm8994-tomtom 575 * snd_card_name is truncated to 32 charaters as per mixer_get_name() implementation 576 * so use min of my_data->snd_card_name and snd_card_name length for comparison 577 */ 578 579 if (my_data->snd_card_name != NULL && 580 strncmp(snd_card_name, my_data->snd_card_name, 581 min(strlen(snd_card_name), strlen(my_data->snd_card_name))) != 0) { 582 ALOGI("%s: found valid sound card %s, but not primary sound card %s", 583 __func__, snd_card_name, my_data->snd_card_name); 584 goto cleanup; 585 } 586 587 ALOGI("%s: found sound card %s, primary sound card expected is %s", 588 __func__, snd_card_name, my_data->snd_card_name); 589 break; 590 cleanup: 591 ++snd_card_num; 592 mixer_close(mixer); 593 mixer = NULL; 594 hw_info_deinit(hw_info); 595 hw_info = NULL; 596 } 597 598 done: 599 mixer_close(mixer); 600 hw_info_deinit(hw_info); 601 602 if (my_data) 603 free(my_data); 604 605 return snd_card_num; 606 } 607