ALSAStreamOps.cpp revision 2c79891211108cd8157124c1b6f9d393729602ff
14765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev/* ALSAStreamOps.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 279746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#define LOG_TAG "ALSAStreamOps" 284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev//#define LOG_NDEBUG 0 299746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#define LOG_NDDEBUG 0 304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <utils/Log.h> 314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <utils/String8.h> 324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <cutils/properties.h> 344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <media/AudioRecord.h> 354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <hardware_legacy/power.h> 36b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani#include "AudioUtil.h" 374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include "AudioHardwareALSA.h" 384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevnamespace android_audio_legacy 404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 42b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani// unused 'enumVal;' is to catch error at compile time if enumVal ever changes 43b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani// or applied on a non-existent enum 44b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani#define ENUM_TO_STRING(var, enumVal) {var = #enumVal; enumVal;} 45b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani 464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// ---------------------------------------------------------------------------- 474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 484765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevALSAStreamOps::ALSAStreamOps(AudioHardwareALSA *parent, alsa_handle_t *handle) : 494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent(parent), 504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mHandle(handle) 514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 544765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevALSAStreamOps::~ALSAStreamOps() 554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev Mutex::Autolock autoLock(mParent->mLock); 574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) || 594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) { 604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((mParent->mVoipStreamCount)) { 614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->mVoipStreamCount--; 624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(mParent->mVoipStreamCount > 0) { 634113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("ALSAStreamOps::close() Ignore"); 644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return ; 654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->mVoipStreamCount = 0; 684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->mVoipBitRate = 0; 694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev close(); 714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for(ALSAHandleList::iterator it = mParent->mDeviceList.begin(); 734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev it != mParent->mDeviceList.end(); ++it) { 744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mHandle == &(*it)) { 754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev it->useCase[0] = 0; 764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->mDeviceList.erase(it); 774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// use emulated popcount optimization 834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// http://www.df.lth.se/~john_e/gems/gem002d.html 844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic inline uint32_t popCount(uint32_t u) 854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev u = ((u&0x55555555) + ((u>>1)&0x55555555)); 874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev u = ((u&0x33333333) + ((u>>2)&0x33333333)); 884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev u = ((u&0x0f0f0f0f) + ((u>>4)&0x0f0f0f0f)); 894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev u = ((u&0x00ff00ff) + ((u>>8)&0x00ff00ff)); 904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev u = ( u&0x0000ffff) + (u>>16); 914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return u; 924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t ALSAStreamOps::set(int *format, 954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint32_t *channels, 964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint32_t *rate, 974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint32_t device) 984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDevices = device; 1004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (channels && *channels != 0) { 1014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mHandle->channels != popCount(*channels)) 1024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return BAD_VALUE; 1034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if (channels) { 1044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *channels = 0; 1054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mHandle->devices & AudioSystem::DEVICE_OUT_ALL) { 1064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev switch(mHandle->channels) { 107bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani case 6: 108bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani case 5: 109bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani *channels |= audio_channel_out_mask_from_count(mHandle->channels); 110bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani break; 111bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani // Do not fall through 1124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 4: 1134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *channels |= AudioSystem::CHANNEL_OUT_BACK_LEFT; 1144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *channels |= AudioSystem::CHANNEL_OUT_BACK_RIGHT; 1154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Fall through... 1164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev default: 1174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 2: 1184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *channels |= AudioSystem::CHANNEL_OUT_FRONT_RIGHT; 1194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Fall through... 1204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 1: 1214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *channels |= AudioSystem::CHANNEL_OUT_FRONT_LEFT; 1224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 1254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev switch(mHandle->channels) { 1269746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_SSR_ENABLED 1274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // For 5.1 recording 1284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 6 : 1294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *channels |= AudioSystem::CHANNEL_IN_5POINT1; 1304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 1324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Do not fall through... 1334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev default: 1344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 2: 1354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *channels |= AudioSystem::CHANNEL_IN_RIGHT; 1364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Fall through... 1374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 1: 1384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *channels |= AudioSystem::CHANNEL_IN_LEFT; 1394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (rate && *rate > 0) { 1454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mHandle->sampleRate != *rate) 1464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return BAD_VALUE; 1474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if (rate) { 1484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *rate = mHandle->sampleRate; 1494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_pcm_format_t iformat = mHandle->format; 1524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (format) { 1544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev switch(*format) { 1554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::FORMAT_DEFAULT: 1564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::PCM_16_BIT: 1594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev iformat = SNDRV_PCM_FORMAT_S16_LE; 1604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::AMR_NB: 1624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::AMR_WB: 1639746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_QCHAT_ENABLED 1644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::EVRC: 1654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::EVRCB: 1664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::EVRCWB: 1674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 1684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev iformat = *format; 1694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::PCM_8_BIT: 1724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev iformat = SNDRV_PCM_FORMAT_S8; 1734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev default: 1764113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("Unknown PCM format %i. Forcing default", *format); 1774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mHandle->format != iformat) 1814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return BAD_VALUE; 1824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev switch(iformat) { 1844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case SNDRV_PCM_FORMAT_S16_LE: 1854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *format = AudioSystem::PCM_16_BIT; 1864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case SNDRV_PCM_FORMAT_S8: 1884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *format = AudioSystem::PCM_8_BIT; 1894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev default: 1914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_ERROR; 1964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 1974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t ALSAStreamOps::setParameters(const String8& keyValuePairs) 1994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 2004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev AudioParameter param = AudioParameter(keyValuePairs); 2014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev String8 key = String8(AudioParameter::keyRouting); 2024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int device; 20374060dee8c9a414ad0345176e2422de18a4ff183ty.lee 20474060dee8c9a414ad0345176e2422de18a4ff183ty.lee#ifdef SEPERATED_AUDIO_INPUT 20574060dee8c9a414ad0345176e2422de18a4ff183ty.lee String8 key_input = String8(AudioParameter::keyInputSource); 20674060dee8c9a414ad0345176e2422de18a4ff183ty.lee int source; 20774060dee8c9a414ad0345176e2422de18a4ff183ty.lee 20874060dee8c9a414ad0345176e2422de18a4ff183ty.lee if (param.getInt(key_input, source) == NO_ERROR) { 20974060dee8c9a414ad0345176e2422de18a4ff183ty.lee ALOGD("setParameters(), input_source = %d", source); 21074060dee8c9a414ad0345176e2422de18a4ff183ty.lee mParent->mALSADevice->setInput(source); 21174060dee8c9a414ad0345176e2422de18a4ff183ty.lee param.remove(key_input); 21274060dee8c9a414ad0345176e2422de18a4ff183ty.lee } 21374060dee8c9a414ad0345176e2422de18a4ff183ty.lee#endif 21474060dee8c9a414ad0345176e2422de18a4ff183ty.lee 2154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.getInt(key, device) == NO_ERROR) { 2164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Ignore routing if device is 0. 2172c79891211108cd8157124c1b6f9d393729602ffsamin.ryu ALOGD("setParameters(): keyRouting with device 0x%x", device); 218466e8a8fa8d4e6186b72c25cd0289356828177b3Eric Laurent // reset to speaker when disconnecting HDMI to avoid timeout due to write errors 219466e8a8fa8d4e6186b72c25cd0289356828177b3Eric Laurent if ((device == 0) && (mDevices == AudioSystem::DEVICE_OUT_AUX_DIGITAL)) { 220466e8a8fa8d4e6186b72c25cd0289356828177b3Eric Laurent device = AudioSystem::DEVICE_OUT_SPEAKER; 221466e8a8fa8d4e6186b72c25cd0289356828177b3Eric Laurent } 2222c79891211108cd8157124c1b6f9d393729602ffsamin.ryu if (device) 2232c79891211108cd8157124c1b6f9d393729602ffsamin.ryu mDevices = device; 2242c79891211108cd8157124c1b6f9d393729602ffsamin.ryu else 2252c79891211108cd8157124c1b6f9d393729602ffsamin.ryu ALOGV("must not change mDevices to 0"); 2262c79891211108cd8157124c1b6f9d393729602ffsamin.ryu 2274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(device) { 2284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->doRouting(device); 2294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param.remove(key); 2314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2329746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_FM_ENABLED 2334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else { 2344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev key = String8(AudioParameter::keyHandleFm); 2354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.getInt(key, device) == NO_ERROR) { 2364113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("setParameters(): handleFm with device %d", device); 2374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDevices = device; 2384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(device) { 2394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->handleFm(device); 2404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param.remove(key); 2424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 2454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_ERROR; 2474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 2484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2494765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevString8 ALSAStreamOps::getParameters(const String8& keys) 2504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 2514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev AudioParameter param = AudioParameter(keys); 2524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev String8 value; 2534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev String8 key = String8(AudioParameter::keyRouting); 2544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.get(key, value) == NO_ERROR) { 2564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param.addInt(key, (int)mDevices); 2574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else { 2599746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_VOIP_ENABLED 2604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev key = String8(AudioParameter::keyVoipCheck); 2614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.get(key, value) == NO_ERROR) { 2624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((!strncmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL, strlen(SND_USE_CASE_VERB_IP_VOICECALL))) || 2634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (!strncmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP, strlen(SND_USE_CASE_MOD_PLAY_VOIP)))) 2644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param.addInt(key, true); 2654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else 2664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param.addInt(key, false); 2674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2684113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev#endif 2694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 270b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani key = String8(AUDIO_PARAMETER_STREAM_SUP_CHANNELS); 271b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani if (param.get(key, value) == NO_ERROR) { 272b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani EDID_AUDIO_INFO info = { 0 }; 273b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani bool first = true; 274b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani value = String8(); 275b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani if (AudioUtil::getHDMIAudioSinkCaps(&info)) { 276b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani for (int i = 0; i < info.nAudioBlocks && i < MAX_EDID_BLOCKS; i++) { 277b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani String8 append; 278b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani switch (info.AudioBlocksArray[i].nChannels) { 279b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani //Do not handle stereo output in Multi-channel cases 280b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani //Stereo case is handled in normal playback path 281b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani case 6: 282b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani ENUM_TO_STRING(append, AUDIO_CHANNEL_OUT_5POINT1); 283b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani break; 284b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani case 8: 285b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani ENUM_TO_STRING(append, AUDIO_CHANNEL_OUT_7POINT1); 286b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani break; 287b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani default: 288b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani ALOGD("Unsupported number of channels %d", info.AudioBlocksArray[i].nChannels); 289b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani break; 290b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani } 291b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani if (!append.isEmpty()) { 292b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani value += (first ? append : String8("|") + append); 293b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani first = false; 294b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani } 295b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani } 296b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani } else { 297b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani ALOGE("Failed to get HDMI sink capabilities"); 298b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani } 299b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani param.add(key, value); 300b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani } 3014113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("getParameters() %s", param.toString().string()); 3024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return param.toString(); 3034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 3044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevuint32_t ALSAStreamOps::sampleRate() const 3064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 3074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return mHandle->sampleRate; 3084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 3094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// 3114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// Return the number of bytes (not frames) 3124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// 3134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevsize_t ALSAStreamOps::bufferSize() const 3144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 3154113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("bufferSize() returns %d", mHandle->bufferSize); 3164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return mHandle->bufferSize; 3174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 3184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevint ALSAStreamOps::format() const 3204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 3214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int audioSystemFormat; 3224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_pcm_format_t ALSAFormat = mHandle->format; 3244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev switch(ALSAFormat) { 3264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case SNDRV_PCM_FORMAT_S8: 3274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev audioSystemFormat = AudioSystem::PCM_8_BIT; 3284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 3294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::AMR_NB: 3314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::AMR_WB: 3329746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_QCHAT_ENABLED 3334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::EVRC: 3344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::EVRCB: 3354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::EVRCWB: 3364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 3374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev audioSystemFormat = mHandle->format; 3384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 3394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case SNDRV_PCM_FORMAT_S16_LE: 3404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev audioSystemFormat = AudioSystem::PCM_16_BIT; 3414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 3424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev default: 3444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev LOG_FATAL("Unknown AudioSystem bit width %d!", audioSystemFormat); 3454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev audioSystemFormat = AudioSystem::PCM_16_BIT; 3464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 3474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3499efed76df6b7c75d170e8f900f875f4329587719SathishKumar Mani ALOGV("ALSAFormat:0x%x,audioSystemFormat:0x%x",ALSAFormat,audioSystemFormat); 3504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return audioSystemFormat; 3514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 3524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevuint32_t ALSAStreamOps::channels() const 3544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 3554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev unsigned int count = mHandle->channels; 3564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint32_t channels = 0; 3574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mDevices & AudioSystem::DEVICE_OUT_ALL) 3594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev switch(count) { 360bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani case 6: 361bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani case 5: 362bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani channels |=audio_channel_out_mask_from_count(count); 363bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani break; 364bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani // Do not fall through 3654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 4: 3664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev channels |= AudioSystem::CHANNEL_OUT_BACK_LEFT; 3674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev channels |= AudioSystem::CHANNEL_OUT_BACK_RIGHT; 3684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Fall through... 3694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev default: 3704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 2: 3714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev channels |= AudioSystem::CHANNEL_OUT_FRONT_RIGHT; 3724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Fall through... 3734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 1: 3744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev channels |= AudioSystem::CHANNEL_OUT_FRONT_LEFT; 3754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 3764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else 3784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev switch(count) { 3799746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_SSR_ENABLED 3804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // For 5.1 recording 3814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 6 : 3824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev channels |= AudioSystem::CHANNEL_IN_5POINT1; 3834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 3844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Do not fall through... 3854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 3864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev default: 3874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 2: 3884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev channels |= AudioSystem::CHANNEL_IN_RIGHT; 3894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Fall through... 3904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 1: 3914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev channels |= AudioSystem::CHANNEL_IN_LEFT; 3924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 3934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return channels; 3964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 3974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid ALSAStreamOps::close() 3994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 4004113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("close"); 4014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((!strncmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL, strlen(SND_USE_CASE_VERB_IP_VOICECALL))) || 4024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (!strncmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP, strlen(SND_USE_CASE_MOD_PLAY_VOIP)))) { 4034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->mVoipBitRate = 0; 4044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->mVoipStreamCount = 0; 4054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->mALSADevice->close(mHandle); 4074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 4084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// 4104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// Set playback or capture PCM device. It's possible to support audio output 4114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// or input from multiple devices by using the ALSA plugins, but this is 4124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// not supported for simplicity. 4134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// 4144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// The AudioHardwareALSA API does not allow one to set the input routing. 4154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// 4164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// If the "routes" value does not map to a valid device, the default playback 4174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// device is used. 4184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// 4194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t ALSAStreamOps::open(int mode) 4204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 4214113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("open"); 4224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return mParent->mALSADevice->open(mHandle); 4234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 4244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} // namespace androidi_audio_legacy 426