14765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev/* AudioStreamOutALSA.cpp 24765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** 34765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** Copyright 2008-2009 Wind River Systems 44765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** Copyright (c) 2011, Code Aurora Forum. All rights reserved. 54765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** 64765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** Licensed under the Apache License, Version 2.0 (the "License"); 74765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** you may not use this file except in compliance with the License. 84765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** You may obtain a copy of the License at 94765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** 104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** http://www.apache.org/licenses/LICENSE-2.0 114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** 124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** Unless required by applicable law or agreed to in writing, software 134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** distributed under the License is distributed on an "AS IS" BASIS, 144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** See the License for the specific language governing permissions and 164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** limitations under the License. 174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev */ 184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <errno.h> 204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <stdarg.h> 214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <sys/stat.h> 224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <fcntl.h> 234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <stdlib.h> 244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <unistd.h> 254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <dlfcn.h> 264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <math.h> 274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 289746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#define LOG_TAG "AudioStreamOutALSA" 294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev//#define LOG_NDEBUG 0 309746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#define LOG_NDDEBUG 0 314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <utils/Log.h> 324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <utils/String8.h> 334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <cutils/properties.h> 354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <media/AudioRecord.h> 364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <hardware_legacy/power.h> 374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include "AudioHardwareALSA.h" 394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#ifndef ALSA_DEFAULT_SAMPLE_RATE 414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#define ALSA_DEFAULT_SAMPLE_RATE 44100 // in Hz 424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevnamespace android_audio_legacy 454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// ---------------------------------------------------------------------------- 484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic const int DEFAULT_SAMPLE_RATE = ALSA_DEFAULT_SAMPLE_RATE; 504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// ---------------------------------------------------------------------------- 524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 534765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevAudioStreamOutALSA::AudioStreamOutALSA(AudioHardwareALSA *parent, alsa_handle_t *handle) : 544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ALSAStreamOps(parent, handle), 554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent(parent), 564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mFrameCount(0) 574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 604765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevAudioStreamOutALSA::~AudioStreamOutALSA() 614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev close(); 634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevuint32_t AudioStreamOutALSA::channels() const 664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int c = ALSAStreamOps::channels(); 684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return c; 694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t AudioStreamOutALSA::setVolume(float left, float right) 724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int vol; 744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev float volume; 754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev status_t status = NO_ERROR; 764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev volume = (left + right) / 2; 784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (volume < 0.0) { 794113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGW("AudioSessionOutALSA::setVolume(%f) under 0.0, assuming 0.0\n", volume); 804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev volume = 0.0; 814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if (volume > 1.0) { 824113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGW("AudioSessionOutALSA::setVolume(%f) over 1.0, assuming 1.0\n", volume); 834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev volume = 1.0; 844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev vol = lrint((volume * 0x2000)+0.5); 864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(!strcmp(mHandle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER) || 884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev !strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_LPA)) { 898a9785b5e6a199a6c64ac671afc2e8036c7ec13fAjay Dudani ALOGV("setLpaVolume(%f)\n", volume); 908a9785b5e6a199a6c64ac671afc2e8036c7ec13fAjay Dudani ALOGV("Setting LPA volume to %d (available range is 0 to 100)\n", vol); 914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mHandle->module->setLpaVolume(vol); 924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return status; 934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else if(!strcmp(mHandle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL) || 954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev !strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL)) { 968a9785b5e6a199a6c64ac671afc2e8036c7ec13fAjay Dudani ALOGV("setCompressedVolume(%f)\n", volume); 978a9785b5e6a199a6c64ac671afc2e8036c7ec13fAjay Dudani ALOGV("Setting Compressed volume to %d (available range is 0 to 100)\n", vol); 984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mHandle->module->setCompressedVolume(vol); 994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return status; 1004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else if(!strncmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL, 1024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev sizeof(mHandle->useCase)) || !strncmp(mHandle->useCase, 1034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev SND_USE_CASE_MOD_PLAY_VOIP, sizeof(mHandle->useCase))) { 1044113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("Avoid Software volume by returning success\n"); 1054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return status; 1064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return INVALID_OPERATION; 1084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 1094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevssize_t AudioStreamOutALSA::write(const void *buffer, size_t bytes) 1114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 1124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int period_size; 1134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev char *use_case; 1144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1154113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("write:: buffer %p, bytes %d", buffer, bytes); 1164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_pcm_sframes_t n = 0; 1184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev size_t sent = 0; 1194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev status_t err; 1204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int write_pending = bytes; 1224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((mHandle->handle == NULL) && (mHandle->rxHandle == NULL) && 1244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) && 1254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) { 1264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->mLock.lock(); 127e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani 128bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani ALOGD("mHandle->useCase: %s", mHandle->useCase); 129e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani snd_use_case_get(mHandle->ucMgr, "_verb", (const char **)&use_case); 130e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) { 131bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani if(!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP)){ 132bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani strlcpy(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL, 133bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani sizeof(SND_USE_CASE_VERB_IP_VOICECALL)); 134bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani } else if(!strcmp(mHandle->useCase,SND_USE_CASE_MOD_PLAY_MUSIC2)) { 135bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani strlcpy(mHandle->useCase, SND_USE_CASE_VERB_HIFI2, 136bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani sizeof(SND_USE_CASE_MOD_PLAY_MUSIC2)); 137bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani } else if (!strcmp(mHandle->useCase,SND_USE_CASE_MOD_PLAY_MUSIC)){ 138bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani strlcpy(mHandle->useCase, SND_USE_CASE_VERB_HIFI, 139bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani sizeof(SND_USE_CASE_MOD_PLAY_MUSIC)); 140bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani } else if(!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC)) { 141bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani strlcpy(mHandle->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC, 142bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani sizeof(SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC)); 1434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 144e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani } else { 145bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani if(!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)){ 146bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani strlcpy(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP, 147bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani sizeof(SND_USE_CASE_MOD_PLAY_VOIP)); 148bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani } else if(!strcmp(mHandle->useCase,SND_USE_CASE_VERB_HIFI2)) { 149bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani strlcpy(mHandle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC2, 150bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani sizeof(SND_USE_CASE_MOD_PLAY_MUSIC2)); 151bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani } else if (!strcmp(mHandle->useCase,SND_USE_CASE_VERB_HIFI)){ 152bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani strlcpy(mHandle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC, 153bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani sizeof(SND_USE_CASE_MOD_PLAY_MUSIC)); 154bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani } else if(!strcmp(mHandle->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) { 155bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani strlcpy(mHandle->useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC, 156bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani sizeof(SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC)); 157e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani } 158e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani } 159e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani free(use_case); 160e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) || 161e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani (!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) { 1629746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED 163e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani if((mDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)|| 164e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani (mDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)|| 165e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani (mDevices & AudioSystem::DEVICE_OUT_PROXY)) { 1664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDevices |= AudioSystem::DEVICE_OUT_PROXY; 1674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mHandle->module->route(mHandle, mDevices , mParent->mode()); 168e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani }else 1694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 170e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani { 171e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani mHandle->module->route(mHandle, mDevices , AudioSystem::MODE_IN_COMMUNICATION); 1724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1739746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED 174e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani } else if((mDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)|| 175e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani (mDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)|| 176e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani (mDevices & AudioSystem::DEVICE_OUT_PROXY)) { 177e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani mDevices |= AudioSystem::DEVICE_OUT_PROXY; 178e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani mHandle->module->route(mHandle, mDevices , mParent->mode()); 1794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 180e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani } else { 181d4f2d069126d564b2ef504e0cb59369d8e1e9f32ty.lee mHandle->module->route(mHandle, mDevices , mParent->mode()); 182e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani } 183e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani if (!strcmp(mHandle->useCase, SND_USE_CASE_VERB_HIFI) || 184bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani !strcmp(mHandle->useCase, SND_USE_CASE_VERB_HIFI2) || 185e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani !strcmp(mHandle->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC) || 186e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani !strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) { 187e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani snd_use_case_set(mHandle->ucMgr, "_verb", mHandle->useCase); 188e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani } else { 189e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani snd_use_case_set(mHandle->ucMgr, "_enamod", mHandle->useCase); 190e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani } 191e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) || 192e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani (!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) { 193e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani err = mHandle->module->startVoipCall(mHandle); 194e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani } 195e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani else 196e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani mHandle->module->open(mHandle); 197e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani if(mHandle->handle == NULL) { 198e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani ALOGE("write:: device open failed"); 199e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani mParent->mLock.unlock(); 2005f24fd93afdcc66bfd9246a0e0000c0fd7283b7fSathishKumar Mani return bytes; 201e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani } 202e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani#ifdef QCOM_USBAUDIO_ENABLED 203e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani if((mHandle->devices == AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET)|| 204e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani (mHandle->devices == AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)){ 205e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) || 206e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani (!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) { 207e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani mParent->musbPlaybackState |= USBPLAYBACKBIT_VOIPCALL; 208e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani } else { 209e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani mParent->startUsbPlaybackIfNotStarted(); 210e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani mParent->musbPlaybackState |= USBPLAYBACKBIT_MUSIC; 211e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani } 2124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 213e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani#endif 214e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani 2154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->mLock.unlock(); 2164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2189746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED 2194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(((mDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET) || 2204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (mDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)) && 2214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (!mParent->musbPlaybackState)) { 2224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->mLock.lock(); 2234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->startUsbPlaybackIfNotStarted(); 2248a9785b5e6a199a6c64ac671afc2e8036c7ec13fAjay Dudani ALOGV("Starting playback on USB"); 2254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL) || 2264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev !strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP)) { 2270a019914794cc27f5dacddf4e5dbc019dbe21788SathishKumar Mani ALOGD("Setting VOIPCALL bit here, musbPlaybackState %d", mParent->musbPlaybackState); 2284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->musbPlaybackState |= USBPLAYBACKBIT_VOIPCALL; 2294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev }else{ 2308a9785b5e6a199a6c64ac671afc2e8036c7ec13fAjay Dudani ALOGV("enabling music, musbPlaybackState: %d ", mParent->musbPlaybackState); 2314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->musbPlaybackState |= USBPLAYBACKBIT_MUSIC; 2324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->mLock.unlock(); 2344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2359746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif 2364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev period_size = mHandle->periodSize; 2384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev do { 2394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (write_pending < period_size) { 2404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev write_pending = period_size; 2414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((mParent->mVoipStreamCount) && (mHandle->rxHandle != 0)) { 2434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev n = pcm_write(mHandle->rxHandle, 2444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (char *)buffer + sent, 2454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev period_size); 2464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if (mHandle->handle != 0){ 2474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev n = pcm_write(mHandle->handle, 2484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (char *)buffer + sent, 2494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev period_size); 2504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (n < 0) { 2529746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani mParent->mLock.lock(); 253e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani if (mHandle->handle != NULL) { 254e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani ALOGE("pcm_write returned error %d, trying to recover\n", n); 255e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani pcm_close(mHandle->handle); 256e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani mHandle->handle = NULL; 257e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani if((!strncmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL, strlen(SND_USE_CASE_VERB_IP_VOICECALL))) || 258e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani (!strncmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP, strlen(SND_USE_CASE_MOD_PLAY_VOIP)))) { 259e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani pcm_close(mHandle->rxHandle); 260e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani mHandle->rxHandle = NULL; 261e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani mHandle->module->startVoipCall(mHandle); 262e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani } 26389c224e298fd280a3f2a69da8cc930ff6d036e18SathishKumar Mani else 264e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani mHandle->module->open(mHandle); 26589c224e298fd280a3f2a69da8cc930ff6d036e18SathishKumar Mani if(mHandle->handle == NULL) { 26689c224e298fd280a3f2a69da8cc930ff6d036e18SathishKumar Mani ALOGE("write:: device re-open failed"); 26789c224e298fd280a3f2a69da8cc930ff6d036e18SathishKumar Mani mParent->mLock.unlock(); 26889c224e298fd280a3f2a69da8cc930ff6d036e18SathishKumar Mani return bytes; 269e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani } 2704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->mLock.unlock(); 2724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev continue; 2734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else { 2754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mFrameCount += n; 2764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev sent += static_cast<ssize_t>((period_size)); 2774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev write_pending -= period_size; 2784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } while ((mHandle->handle||(mHandle->rxHandle && mParent->mVoipStreamCount)) && sent < bytes); 2814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return sent; 2834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 2844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t AudioStreamOutALSA::dump(int fd, const Vector<String16>& args) 2864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 2874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_ERROR; 2884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 2894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t AudioStreamOutALSA::open(int mode) 2914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 2924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev Mutex::Autolock autoLock(mParent->mLock); 2934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return ALSAStreamOps::open(mode); 2954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 2964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t AudioStreamOutALSA::close() 2984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 2994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev Mutex::Autolock autoLock(mParent->mLock); 3004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3018a9785b5e6a199a6c64ac671afc2e8036c7ec13fAjay Dudani ALOGV("close"); 3024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) || 3034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) { 3044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((mParent->mVoipStreamCount)) { 3059746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED 3064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(mParent->mVoipStreamCount == 1) { 3078a9785b5e6a199a6c64ac671afc2e8036c7ec13fAjay Dudani ALOGV("Deregistering VOIP Call bit, musbPlaybackState:%d, musbRecordingState: %d", 3084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->musbPlaybackState, mParent->musbRecordingState); 3094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->musbPlaybackState &= ~USBPLAYBACKBIT_VOIPCALL; 3104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->musbRecordingState &= ~USBRECBIT_VOIPCALL; 3114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->closeUsbPlaybackIfNothingActive(); 3124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->closeUsbRecordingIfNothingActive(); 3134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3149746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif 3154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_ERROR; 3164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->mVoipStreamCount = 0; 3189746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani } 3199746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED 3209746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani else if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) || 3214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_LPA))) { 3224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->musbPlaybackState &= ~USBPLAYBACKBIT_LPA; 3234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 3244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->musbPlaybackState &= ~USBPLAYBACKBIT_MUSIC; 3254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->closeUsbPlaybackIfNothingActive(); 3289746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif 3294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ALSAStreamOps::close(); 3314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_ERROR; 3334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 3344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t AudioStreamOutALSA::standby() 3364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 3374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev Mutex::Autolock autoLock(mParent->mLock); 3384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3398a9785b5e6a199a6c64ac671afc2e8036c7ec13fAjay Dudani ALOGV("standby"); 3404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) || 3424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) { 3434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_ERROR; 3444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3469746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED 3474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) || 3484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_LPA))) { 3498a9785b5e6a199a6c64ac671afc2e8036c7ec13fAjay Dudani ALOGV("Deregistering LPA bit"); 3504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->musbPlaybackState &= ~USBPLAYBACKBIT_LPA; 3514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 3528a9785b5e6a199a6c64ac671afc2e8036c7ec13fAjay Dudani ALOGV("Deregistering MUSIC bit, musbPlaybackState: %d", mParent->musbPlaybackState); 3534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->musbPlaybackState &= ~USBPLAYBACKBIT_MUSIC; 3544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3559746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif 3564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mHandle->module->standby(mHandle); 3584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3599746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED 3604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->closeUsbPlaybackIfNothingActive(); 3619746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif 3624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mFrameCount = 0; 3644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_ERROR; 3664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 3674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#define USEC_TO_MSEC(x) ((x + 999) / 1000) 3694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevuint32_t AudioStreamOutALSA::latency() const 3714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 3724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Android wants latency in milliseconds. 3734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return USEC_TO_MSEC (mHandle->latency); 3744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 3754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// return the number of audio frames written by the audio dsp to DAC since 3774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// the output has exited standby 3784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t AudioStreamOutALSA::getRenderPosition(uint32_t *dspFrames) 3794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 3804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *dspFrames = mFrameCount; 3814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_ERROR; 3824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 3834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} // namespace android_audio_legacy 385