1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18#define LOG_TAG "qcom_audio_hw_hal" 19//#define LOG_NDEBUG 0 20 21#include <stdint.h> 22 23#include <hardware/hardware.h> 24#include <system/audio.h> 25#include <hardware/audio.h> 26 27#include <hardware_legacy/AudioHardwareInterface.h> 28#include <hardware_legacy/AudioSystemLegacy.h> 29 30namespace android_audio_legacy { 31 32extern "C" { 33 34struct qcom_audio_module { 35 struct audio_module module; 36}; 37 38struct qcom_audio_device { 39 struct audio_hw_device device; 40 41 struct AudioHardwareInterface *hwif; 42}; 43 44struct qcom_stream_out { 45 struct audio_stream_out stream; 46 47 AudioStreamOut *qcom_out; 48}; 49 50struct qcom_stream_in { 51 struct audio_stream_in stream; 52 53 AudioStreamIn *qcom_in; 54}; 55 56 57enum { 58 HAL_API_REV_1_0, 59 HAL_API_REV_2_0, 60 HAL_API_REV_NUM 61} hal_api_rev; 62 63static uint32_t audio_device_conv_table[][HAL_API_REV_NUM] = 64{ 65 /* output devices */ 66 { AudioSystem::DEVICE_OUT_EARPIECE, AUDIO_DEVICE_OUT_EARPIECE }, 67 { AudioSystem::DEVICE_OUT_SPEAKER, AUDIO_DEVICE_OUT_SPEAKER }, 68 { AudioSystem::DEVICE_OUT_WIRED_HEADSET, AUDIO_DEVICE_OUT_WIRED_HEADSET }, 69 { AudioSystem::DEVICE_OUT_WIRED_HEADPHONE, AUDIO_DEVICE_OUT_WIRED_HEADPHONE }, 70 { AudioSystem::DEVICE_OUT_BLUETOOTH_SCO, AUDIO_DEVICE_OUT_BLUETOOTH_SCO }, 71 { AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET }, 72 { AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT }, 73 { AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP }, 74 { AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES }, 75 { AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER }, 76 { AudioSystem::DEVICE_OUT_AUX_DIGITAL, AUDIO_DEVICE_OUT_AUX_DIGITAL }, 77 { AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET, AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET }, 78 { AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET }, 79 { AudioSystem::DEVICE_OUT_DEFAULT, AUDIO_DEVICE_OUT_DEFAULT }, 80#ifdef QCOM_ANC_HEADSET_ENABLED 81 { AudioSystem::DEVICE_OUT_ANC_HEADSET, AUDIO_DEVICE_OUT_ANC_HEADSET }, 82 { AudioSystem::DEVICE_OUT_ANC_HEADPHONE, AUDIO_DEVICE_OUT_ANC_HEADPHONE }, 83#endif 84#ifdef QCOM_FM_ENABLED 85 { AudioSystem::DEVICE_OUT_FM, AUDIO_DEVICE_OUT_FM }, 86#endif 87#ifdef QCOM_FM_TX_ENABLED 88 { AudioSystem::DEVICE_OUT_FM_TX, AUDIO_DEVICE_OUT_FM_TX }, 89#endif 90#ifdef QCOM_VOIP_ENABLED 91 { AudioSystem::DEVICE_OUT_DIRECTOUTPUT, AUDIO_DEVICE_OUT_DIRECTOUTPUT }, 92#endif 93#ifdef QCOM_PROXY_DEVICE_ENABLED 94 { AudioSystem::DEVICE_OUT_PROXY, AUDIO_DEVICE_OUT_PROXY }, 95#endif 96 /* input devices */ 97 { AudioSystem::DEVICE_IN_COMMUNICATION, AUDIO_DEVICE_IN_COMMUNICATION }, 98 { AudioSystem::DEVICE_IN_AMBIENT, AUDIO_DEVICE_IN_AMBIENT }, 99 { AudioSystem::DEVICE_IN_BUILTIN_MIC, AUDIO_DEVICE_IN_BUILTIN_MIC }, 100 { AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET }, 101 { AudioSystem::DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_WIRED_HEADSET }, 102 { AudioSystem::DEVICE_IN_AUX_DIGITAL, AUDIO_DEVICE_IN_AUX_DIGITAL }, 103 { AudioSystem::DEVICE_IN_VOICE_CALL, AUDIO_DEVICE_IN_VOICE_CALL }, 104 { AudioSystem::DEVICE_IN_BACK_MIC, AUDIO_DEVICE_IN_BACK_MIC }, 105 { AudioSystem::DEVICE_IN_DEFAULT, AUDIO_DEVICE_IN_DEFAULT }, 106#ifdef QCOM_ANC_HEADSET_ENABLED 107 { AudioSystem::DEVICE_IN_ANC_HEADSET, AUDIO_DEVICE_IN_ANC_HEADSET }, 108#endif 109#ifdef QCOM_FM_ENABLED 110 { AudioSystem::DEVICE_IN_FM_RX, AUDIO_DEVICE_IN_FM_RX }, 111 { AudioSystem::DEVICE_IN_FM_RX_A2DP, AUDIO_DEVICE_IN_FM_RX_A2DP }, 112#endif 113}; 114 115static uint32_t convert_audio_device(uint32_t from_device, int from_rev, int to_rev) 116{ 117 const uint32_t k_num_devices = sizeof(audio_device_conv_table)/sizeof(uint32_t)/HAL_API_REV_NUM; 118 uint32_t to_device = AUDIO_DEVICE_NONE; 119 uint32_t in_bit = 0; 120 121 if (from_rev != HAL_API_REV_1_0) { 122 in_bit = from_device & AUDIO_DEVICE_BIT_IN; 123 from_device &= ~AUDIO_DEVICE_BIT_IN; 124 } 125 126 while (from_device) { 127 uint32_t i = 31 - __builtin_clz(from_device); 128 uint32_t cur_device = (1 << i) | in_bit; 129 130 for (i = 0; i < k_num_devices; i++) { 131 if (audio_device_conv_table[i][from_rev] == cur_device) { 132 to_device |= audio_device_conv_table[i][to_rev]; 133 break; 134 } 135 } 136 from_device &= ~cur_device; 137 } 138 return to_device; 139} 140 141/** audio_stream_out implementation **/ 142static uint32_t out_get_sample_rate(const struct audio_stream *stream) 143{ 144 const struct qcom_stream_out *out = 145 reinterpret_cast<const struct qcom_stream_out *>(stream); 146 return out->qcom_out->sampleRate(); 147} 148 149static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate) 150{ 151 struct qcom_stream_out *out = 152 reinterpret_cast<struct qcom_stream_out *>(stream); 153 154 ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__); 155 /* TODO: implement this */ 156 return 0; 157} 158 159static size_t out_get_buffer_size(const struct audio_stream *stream) 160{ 161 const struct qcom_stream_out *out = 162 reinterpret_cast<const struct qcom_stream_out *>(stream); 163 return out->qcom_out->bufferSize(); 164} 165 166static audio_channel_mask_t out_get_channels(const struct audio_stream *stream) 167{ 168 const struct qcom_stream_out *out = 169 reinterpret_cast<const struct qcom_stream_out *>(stream); 170 return out->qcom_out->channels(); 171} 172 173static audio_format_t out_get_format(const struct audio_stream *stream) 174{ 175 const struct qcom_stream_out *out = 176 reinterpret_cast<const struct qcom_stream_out *>(stream); 177 return (audio_format_t)out->qcom_out->format(); 178} 179 180static int out_set_format(struct audio_stream *stream, audio_format_t format) 181{ 182 struct qcom_stream_out *out = 183 reinterpret_cast<struct qcom_stream_out *>(stream); 184 ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__); 185 /* TODO: implement me */ 186 return 0; 187} 188 189static int out_standby(struct audio_stream *stream) 190{ 191 struct qcom_stream_out *out = 192 reinterpret_cast<struct qcom_stream_out *>(stream); 193 return out->qcom_out->standby(); 194} 195 196static int out_dump(const struct audio_stream *stream, int fd) 197{ 198 const struct qcom_stream_out *out = 199 reinterpret_cast<const struct qcom_stream_out *>(stream); 200 Vector<String16> args; 201 return out->qcom_out->dump(fd, args); 202} 203 204static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) 205{ 206 struct qcom_stream_out *out = 207 reinterpret_cast<struct qcom_stream_out *>(stream); 208 int val; 209 String8 s8 = String8(kvpairs); 210 AudioParameter parms = AudioParameter(String8(kvpairs)); 211 212 if (parms.getInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val) == NO_ERROR) { 213 val = convert_audio_device(val, HAL_API_REV_2_0, HAL_API_REV_1_0); 214 parms.remove(String8(AUDIO_PARAMETER_STREAM_ROUTING)); 215 parms.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val); 216 s8 = parms.toString(); 217 } 218 219 return out->qcom_out->setParameters(s8); 220} 221 222static char * out_get_parameters(const struct audio_stream *stream, const char *keys) 223{ 224 const struct qcom_stream_out *out = 225 reinterpret_cast<const struct qcom_stream_out *>(stream); 226 String8 s8; 227 int val; 228 229 s8 = out->qcom_out->getParameters(String8(keys)); 230 231 AudioParameter parms = AudioParameter(s8); 232 if (parms.getInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val) == NO_ERROR) { 233 val = convert_audio_device(val, HAL_API_REV_1_0, HAL_API_REV_2_0); 234 parms.remove(String8(AUDIO_PARAMETER_STREAM_ROUTING)); 235 parms.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val); 236 s8 = parms.toString(); 237 } 238 239 return strdup(s8.string()); 240} 241 242static uint32_t out_get_latency(const struct audio_stream_out *stream) 243{ 244 const struct qcom_stream_out *out = 245 reinterpret_cast<const struct qcom_stream_out *>(stream); 246 return out->qcom_out->latency(); 247} 248 249static int out_set_volume(struct audio_stream_out *stream, float left, 250 float right) 251{ 252 struct qcom_stream_out *out = 253 reinterpret_cast<struct qcom_stream_out *>(stream); 254 return out->qcom_out->setVolume(left, right); 255} 256 257static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, 258 size_t bytes) 259{ 260 struct qcom_stream_out *out = 261 reinterpret_cast<struct qcom_stream_out *>(stream); 262 return out->qcom_out->write(buffer, bytes); 263} 264 265static int out_get_render_position(const struct audio_stream_out *stream, 266 uint32_t *dsp_frames) 267{ 268 const struct qcom_stream_out *out = 269 reinterpret_cast<const struct qcom_stream_out *>(stream); 270 return out->qcom_out->getRenderPosition(dsp_frames); 271} 272 273static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 274{ 275 return 0; 276} 277 278static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 279{ 280 return 0; 281} 282 283static int out_get_next_write_timestamp(const struct audio_stream_out *stream, 284 int64_t *timestamp) 285{ 286 const struct qcom_stream_out *out = 287 reinterpret_cast<const struct qcom_stream_out *>(stream); 288 return out->qcom_out->getNextWriteTimestamp(timestamp); 289} 290 291/** audio_stream_in implementation **/ 292static uint32_t in_get_sample_rate(const struct audio_stream *stream) 293{ 294 const struct qcom_stream_in *in = 295 reinterpret_cast<const struct qcom_stream_in *>(stream); 296 return in->qcom_in->sampleRate(); 297} 298 299static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate) 300{ 301 struct qcom_stream_in *in = 302 reinterpret_cast<struct qcom_stream_in *>(stream); 303 304 ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__); 305 /* TODO: implement this */ 306 return 0; 307} 308 309static size_t in_get_buffer_size(const struct audio_stream *stream) 310{ 311 const struct qcom_stream_in *in = 312 reinterpret_cast<const struct qcom_stream_in *>(stream); 313 return in->qcom_in->bufferSize(); 314} 315 316static audio_channel_mask_t in_get_channels(const struct audio_stream *stream) 317{ 318 const struct qcom_stream_in *in = 319 reinterpret_cast<const struct qcom_stream_in *>(stream); 320 return in->qcom_in->channels(); 321} 322 323static audio_format_t in_get_format(const struct audio_stream *stream) 324{ 325 const struct qcom_stream_in *in = 326 reinterpret_cast<const struct qcom_stream_in *>(stream); 327 return (audio_format_t)in->qcom_in->format(); 328} 329 330static int in_set_format(struct audio_stream *stream, audio_format_t format) 331{ 332 struct qcom_stream_in *in = 333 reinterpret_cast<struct qcom_stream_in *>(stream); 334 ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__); 335 /* TODO: implement me */ 336 return 0; 337} 338 339static int in_standby(struct audio_stream *stream) 340{ 341 struct qcom_stream_in *in = reinterpret_cast<struct qcom_stream_in *>(stream); 342 return in->qcom_in->standby(); 343} 344 345static int in_dump(const struct audio_stream *stream, int fd) 346{ 347 const struct qcom_stream_in *in = 348 reinterpret_cast<const struct qcom_stream_in *>(stream); 349 Vector<String16> args; 350 return in->qcom_in->dump(fd, args); 351} 352 353static int in_set_parameters(struct audio_stream *stream, const char *kvpairs) 354{ 355 struct qcom_stream_in *in = 356 reinterpret_cast<struct qcom_stream_in *>(stream); 357 int val; 358 AudioParameter parms = AudioParameter(String8(kvpairs)); 359 String8 s8 = String8(kvpairs); 360 361 if (parms.getInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val) == NO_ERROR) { 362 val = convert_audio_device(val, HAL_API_REV_2_0, HAL_API_REV_1_0); 363 parms.remove(String8(AUDIO_PARAMETER_STREAM_ROUTING)); 364 parms.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val); 365 s8 = parms.toString(); 366 } 367 368 return in->qcom_in->setParameters(s8); 369} 370 371static char * in_get_parameters(const struct audio_stream *stream, 372 const char *keys) 373{ 374 const struct qcom_stream_in *in = 375 reinterpret_cast<const struct qcom_stream_in *>(stream); 376 String8 s8; 377 int val; 378 379 s8 = in->qcom_in->getParameters(String8(keys)); 380 381 AudioParameter parms = AudioParameter(s8); 382 if (parms.getInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val) == NO_ERROR) { 383 val = convert_audio_device(val, HAL_API_REV_1_0, HAL_API_REV_2_0); 384 parms.remove(String8(AUDIO_PARAMETER_STREAM_ROUTING)); 385 parms.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val); 386 s8 = parms.toString(); 387 } 388 389 return strdup(s8.string()); 390} 391 392static int in_set_gain(struct audio_stream_in *stream, float gain) 393{ 394 struct qcom_stream_in *in = 395 reinterpret_cast<struct qcom_stream_in *>(stream); 396 return in->qcom_in->setGain(gain); 397} 398 399static ssize_t in_read(struct audio_stream_in *stream, void* buffer, 400 size_t bytes) 401{ 402 struct qcom_stream_in *in = 403 reinterpret_cast<struct qcom_stream_in *>(stream); 404 return in->qcom_in->read(buffer, bytes); 405} 406 407static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream) 408{ 409 struct qcom_stream_in *in = 410 reinterpret_cast<struct qcom_stream_in *>(stream); 411 return in->qcom_in->getInputFramesLost(); 412} 413 414static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 415{ 416 const struct qcom_stream_in *in = 417 reinterpret_cast<const struct qcom_stream_in *>(stream); 418 return in->qcom_in->addAudioEffect(effect); 419} 420 421static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 422{ 423 const struct qcom_stream_in *in = 424 reinterpret_cast<const struct qcom_stream_in *>(stream); 425 return in->qcom_in->removeAudioEffect(effect); 426} 427 428/** audio_hw_device implementation **/ 429static inline struct qcom_audio_device * to_ladev(struct audio_hw_device *dev) 430{ 431 return reinterpret_cast<struct qcom_audio_device *>(dev); 432} 433 434static inline const struct qcom_audio_device * to_cladev(const struct audio_hw_device *dev) 435{ 436 return reinterpret_cast<const struct qcom_audio_device *>(dev); 437} 438 439static int adev_init_check(const struct audio_hw_device *dev) 440{ 441 const struct qcom_audio_device *qadev = to_cladev(dev); 442 443 return qadev->hwif->initCheck(); 444} 445 446static int adev_set_voice_volume(struct audio_hw_device *dev, float volume) 447{ 448 struct qcom_audio_device *qadev = to_ladev(dev); 449 return qadev->hwif->setVoiceVolume(volume); 450} 451 452static int adev_set_master_volume(struct audio_hw_device *dev, float volume) 453{ 454 struct qcom_audio_device *qadev = to_ladev(dev); 455 return qadev->hwif->setMasterVolume(volume); 456} 457 458static int adev_get_master_volume(struct audio_hw_device *dev, float *volume) { 459 460 struct qcom_audio_device *qadev = to_ladev(dev); 461 return qadev->hwif->getMasterVolume(volume); 462} 463 464#ifdef QCOM_FM_ENABLED 465static int adev_set_fm_volume(struct audio_hw_device *dev, float volume) 466{ 467 struct qcom_audio_device *qadev = to_ladev(dev); 468 return qadev->hwif->setFmVolume(volume); 469} 470#endif 471 472static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode) 473{ 474 struct qcom_audio_device *qadev = to_ladev(dev); 475 return qadev->hwif->setMode(mode); 476} 477 478static int adev_set_mic_mute(struct audio_hw_device *dev, bool state) 479{ 480 struct qcom_audio_device *qadev = to_ladev(dev); 481 return qadev->hwif->setMicMute(state); 482} 483 484static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state) 485{ 486 const struct qcom_audio_device *qadev = to_cladev(dev); 487 return qadev->hwif->getMicMute(state); 488} 489 490static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) 491{ 492 struct qcom_audio_device *qadev = to_ladev(dev); 493 return qadev->hwif->setParameters(String8(kvpairs)); 494} 495 496static char * adev_get_parameters(const struct audio_hw_device *dev, 497 const char *keys) 498{ 499 const struct qcom_audio_device *qadev = to_cladev(dev); 500 String8 s8; 501 502 s8 = qadev->hwif->getParameters(String8(keys)); 503 return strdup(s8.string()); 504} 505 506static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev, 507 const struct audio_config *config) 508{ 509 const struct qcom_audio_device *qadev = to_cladev(dev); 510 uint8_t channelCount = popcount(config->channel_mask); 511 return qadev->hwif->getInputBufferSize(config->sample_rate, config->format, channelCount); 512} 513 514#ifdef QCOM_TUNNEL_LPA_ENABLED 515static int adev_open_output_session(struct audio_hw_device *dev, 516 uint32_t devices, 517 int *format, 518 int sessionId, 519 uint32_t samplingRate, 520 uint32_t channels, 521 struct audio_stream_out **stream_out) 522{ 523 struct qcom_audio_device *qadev = to_ladev(dev); 524 status_t status; 525 struct qcom_stream_out *out; 526 int ret; 527 528 out = (struct qcom_stream_out *)calloc(1, sizeof(*out)); 529 if (!out) 530 return -ENOMEM; 531 532 out->qcom_out = qadev->hwif->openOutputSession(devices, format,&status,sessionId,samplingRate,channels); 533 if (!out->qcom_out) { 534 ret = status; 535 goto err_open; 536 } 537 538 out->stream.common.standby = out_standby; 539 out->stream.common.set_parameters = out_set_parameters; 540 out->stream.set_volume = out_set_volume; 541 542 *stream_out = &out->stream; 543 return 0; 544 545err_open: 546 free(out); 547 *stream_out = NULL; 548 return ret; 549} 550#endif 551 552static int adev_open_output_stream(struct audio_hw_device *dev, 553 audio_io_handle_t handle, 554 audio_devices_t devices, 555 audio_output_flags_t flags, 556 struct audio_config *config, 557 struct audio_stream_out **stream_out, 558 const char *address __unused) 559{ 560 struct qcom_audio_device *qadev = to_ladev(dev); 561 status_t status; 562 struct qcom_stream_out *out; 563 int ret; 564 565 out = (struct qcom_stream_out *)calloc(1, sizeof(*out)); 566 if (!out) 567 return -ENOMEM; 568 569 devices = convert_audio_device(devices, HAL_API_REV_2_0, HAL_API_REV_1_0); 570 status = static_cast<audio_output_flags_t> (flags); 571 572 out->qcom_out = qadev->hwif->openOutputStream(devices, 573 (int *)&config->format, 574 &config->channel_mask, 575 &config->sample_rate, 576 &status); 577 if (!out->qcom_out) { 578 ret = status; 579 goto err_open; 580 } 581 582 out->stream.common.get_sample_rate = out_get_sample_rate; 583 out->stream.common.set_sample_rate = out_set_sample_rate; 584 out->stream.common.get_buffer_size = out_get_buffer_size; 585 out->stream.common.get_channels = out_get_channels; 586 out->stream.common.get_format = out_get_format; 587 out->stream.common.set_format = out_set_format; 588 out->stream.common.standby = out_standby; 589 out->stream.common.dump = out_dump; 590 out->stream.common.set_parameters = out_set_parameters; 591 out->stream.common.get_parameters = out_get_parameters; 592 out->stream.common.add_audio_effect = out_add_audio_effect; 593 out->stream.common.remove_audio_effect = out_remove_audio_effect; 594 out->stream.get_latency = out_get_latency; 595 out->stream.set_volume = out_set_volume; 596 out->stream.write = out_write; 597 out->stream.get_render_position = out_get_render_position; 598 out->stream.get_next_write_timestamp = out_get_next_write_timestamp; 599 600 *stream_out = &out->stream; 601 return 0; 602 603err_open: 604 free(out); 605 *stream_out = NULL; 606 return ret; 607} 608 609static void adev_close_output_stream(struct audio_hw_device *dev, 610 struct audio_stream_out* stream) 611{ 612 struct qcom_audio_device *qadev = to_ladev(dev); 613 struct qcom_stream_out *out = reinterpret_cast<struct qcom_stream_out *>(stream); 614 615 qadev->hwif->closeOutputStream(out->qcom_out); 616 free(out); 617} 618 619/** This method creates and opens the audio hardware input stream */ 620static int adev_open_input_stream(struct audio_hw_device *dev, 621 audio_io_handle_t handle, 622 audio_devices_t devices, 623 audio_config *config, 624 audio_stream_in **stream_in, 625 audio_input_flags_t flags __unused, 626 const char *address __unused, 627 audio_source_t source __unused) 628{ 629 struct qcom_audio_device *qadev = to_ladev(dev); 630 status_t status; 631 struct qcom_stream_in *in; 632 int ret; 633 634 in = (struct qcom_stream_in *)calloc(1, sizeof(*in)); 635 if (!in) 636 return -ENOMEM; 637 638 devices = convert_audio_device(devices, HAL_API_REV_2_0, HAL_API_REV_1_0); 639 640 in->qcom_in = qadev->hwif->openInputStream(devices, (int *)&config->format, 641 &config->channel_mask, 642 &config->sample_rate, 643 &status, 644 (AudioSystem::audio_in_acoustics)0); 645 if (!in->qcom_in) { 646 ret = status; 647 goto err_open; 648 } 649 650 in->stream.common.get_sample_rate = in_get_sample_rate; 651 in->stream.common.set_sample_rate = in_set_sample_rate; 652 in->stream.common.get_buffer_size = in_get_buffer_size; 653 in->stream.common.get_channels = in_get_channels; 654 in->stream.common.get_format = in_get_format; 655 in->stream.common.set_format = in_set_format; 656 in->stream.common.standby = in_standby; 657 in->stream.common.dump = in_dump; 658 in->stream.common.set_parameters = in_set_parameters; 659 in->stream.common.get_parameters = in_get_parameters; 660 in->stream.common.add_audio_effect = in_add_audio_effect; 661 in->stream.common.remove_audio_effect = in_remove_audio_effect; 662 in->stream.set_gain = in_set_gain; 663 in->stream.read = in_read; 664 in->stream.get_input_frames_lost = in_get_input_frames_lost; 665 666 *stream_in = &in->stream; 667 return 0; 668 669err_open: 670 free(in); 671 *stream_in = NULL; 672 return ret; 673} 674 675static void adev_close_input_stream(struct audio_hw_device *dev, 676 struct audio_stream_in *stream) 677{ 678 struct qcom_audio_device *qadev = to_ladev(dev); 679 struct qcom_stream_in *in = 680 reinterpret_cast<struct qcom_stream_in *>(stream); 681 682 qadev->hwif->closeInputStream(in->qcom_in); 683 free(in); 684} 685 686static int adev_dump(const struct audio_hw_device *dev, int fd) 687{ 688 const struct qcom_audio_device *qadev = to_cladev(dev); 689 Vector<String16> args; 690 691 return qadev->hwif->dumpState(fd, args); 692} 693 694static int qcom_adev_close(hw_device_t* device) 695{ 696 struct audio_hw_device *hwdev = 697 reinterpret_cast<struct audio_hw_device *>(device); 698 struct qcom_audio_device *qadev = to_ladev(hwdev); 699 700 if (!qadev) 701 return 0; 702 703 if (qadev->hwif) 704 delete qadev->hwif; 705 706 free(qadev); 707 return 0; 708} 709 710static int qcom_adev_open(const hw_module_t* module, const char* name, 711 hw_device_t** device) 712{ 713 struct qcom_audio_device *qadev; 714 int ret; 715 716 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) 717 return -EINVAL; 718 719 qadev = (struct qcom_audio_device *)calloc(1, sizeof(*qadev)); 720 if (!qadev) 721 return -ENOMEM; 722 723 qadev->device.common.tag = HARDWARE_DEVICE_TAG; 724 qadev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0; 725 qadev->device.common.module = const_cast<hw_module_t*>(module); 726 qadev->device.common.close = qcom_adev_close; 727 728 qadev->device.init_check = adev_init_check; 729 qadev->device.set_voice_volume = adev_set_voice_volume; 730 qadev->device.set_master_volume = adev_set_master_volume; 731 qadev->device.get_master_volume = adev_get_master_volume; 732#ifdef QCOM_FM_ENABLED 733 qadev->device.set_fm_volume = adev_set_fm_volume; 734#endif 735 qadev->device.set_mode = adev_set_mode; 736 qadev->device.set_mic_mute = adev_set_mic_mute; 737 qadev->device.get_mic_mute = adev_get_mic_mute; 738 qadev->device.set_parameters = adev_set_parameters; 739 qadev->device.get_parameters = adev_get_parameters; 740 qadev->device.get_input_buffer_size = adev_get_input_buffer_size; 741 qadev->device.open_output_stream = adev_open_output_stream; 742#ifdef QCOM_TUNNEL_LPA_ENABLED 743 qadev->device.open_output_session = adev_open_output_session; 744#endif 745 qadev->device.close_output_stream = adev_close_output_stream; 746 qadev->device.open_input_stream = adev_open_input_stream; 747 qadev->device.close_input_stream = adev_close_input_stream; 748 qadev->device.dump = adev_dump; 749 750 qadev->hwif = createAudioHardware(); 751 if (!qadev->hwif) { 752 ret = -EIO; 753 goto err_create_audio_hw; 754 } 755 756 *device = &qadev->device.common; 757 758 return 0; 759 760err_create_audio_hw: 761 free(qadev); 762 return ret; 763} 764 765static struct hw_module_methods_t qcom_audio_module_methods = { 766 open: qcom_adev_open 767}; 768 769struct qcom_audio_module HAL_MODULE_INFO_SYM = { 770 module: { 771 common: { 772 tag: HARDWARE_MODULE_TAG, 773 module_api_version: AUDIO_MODULE_API_VERSION_0_1, 774 hal_api_version: HARDWARE_HAL_API_VERSION, 775 id: AUDIO_HARDWARE_MODULE_ID, 776 name: "QCOM Audio HW HAL", 777 author: "Code Aurora Forum", 778 methods: &qcom_audio_module_methods, 779 dso : NULL, 780 reserved : {0}, 781 }, 782 }, 783}; 784 785}; // extern "C" 786 787}; // namespace android_audio_legacy 788