ALSAStreamOps.cpp revision b357a77dc9c72cb6e327e945421f440052233b51
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) { 1074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 4: 1084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *channels |= AudioSystem::CHANNEL_OUT_BACK_LEFT; 1094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *channels |= AudioSystem::CHANNEL_OUT_BACK_RIGHT; 1104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Fall through... 1114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev default: 1124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 2: 1134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *channels |= AudioSystem::CHANNEL_OUT_FRONT_RIGHT; 1144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Fall through... 1154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 1: 1164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *channels |= AudioSystem::CHANNEL_OUT_FRONT_LEFT; 1174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 1204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev switch(mHandle->channels) { 1219746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_SSR_ENABLED 1224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // For 5.1 recording 1234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 6 : 1244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *channels |= AudioSystem::CHANNEL_IN_5POINT1; 1254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 1274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Do not fall through... 1284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev default: 1294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 2: 1304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *channels |= AudioSystem::CHANNEL_IN_RIGHT; 1314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Fall through... 1324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 1: 1334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *channels |= AudioSystem::CHANNEL_IN_LEFT; 1344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (rate && *rate > 0) { 1404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mHandle->sampleRate != *rate) 1414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return BAD_VALUE; 1424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if (rate) { 1434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *rate = mHandle->sampleRate; 1444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_pcm_format_t iformat = mHandle->format; 1474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (format) { 1494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev switch(*format) { 1504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::FORMAT_DEFAULT: 1514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::PCM_16_BIT: 1544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev iformat = SNDRV_PCM_FORMAT_S16_LE; 1554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::AMR_NB: 1574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::AMR_WB: 1589746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_QCHAT_ENABLED 1594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::EVRC: 1604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::EVRCB: 1614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::EVRCWB: 1624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 1634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev iformat = *format; 1644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::PCM_8_BIT: 1674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev iformat = SNDRV_PCM_FORMAT_S8; 1684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev default: 1714113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("Unknown PCM format %i. Forcing default", *format); 1724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mHandle->format != iformat) 1764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return BAD_VALUE; 1774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev switch(iformat) { 1794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case SNDRV_PCM_FORMAT_S16_LE: 1804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *format = AudioSystem::PCM_16_BIT; 1814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case SNDRV_PCM_FORMAT_S8: 1834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *format = AudioSystem::PCM_8_BIT; 1844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev default: 1864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_ERROR; 1914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 1924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t ALSAStreamOps::setParameters(const String8& keyValuePairs) 1944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 1954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev AudioParameter param = AudioParameter(keyValuePairs); 1964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev String8 key = String8(AudioParameter::keyRouting); 1974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int device; 19874060dee8c9a414ad0345176e2422de18a4ff183ty.lee 19974060dee8c9a414ad0345176e2422de18a4ff183ty.lee#ifdef SEPERATED_AUDIO_INPUT 20074060dee8c9a414ad0345176e2422de18a4ff183ty.lee String8 key_input = String8(AudioParameter::keyInputSource); 20174060dee8c9a414ad0345176e2422de18a4ff183ty.lee int source; 20274060dee8c9a414ad0345176e2422de18a4ff183ty.lee 20374060dee8c9a414ad0345176e2422de18a4ff183ty.lee if (param.getInt(key_input, source) == NO_ERROR) { 20474060dee8c9a414ad0345176e2422de18a4ff183ty.lee ALOGD("setParameters(), input_source = %d", source); 20574060dee8c9a414ad0345176e2422de18a4ff183ty.lee mParent->mALSADevice->setInput(source); 20674060dee8c9a414ad0345176e2422de18a4ff183ty.lee param.remove(key_input); 20774060dee8c9a414ad0345176e2422de18a4ff183ty.lee } 20874060dee8c9a414ad0345176e2422de18a4ff183ty.lee#endif 20974060dee8c9a414ad0345176e2422de18a4ff183ty.lee 2104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.getInt(key, device) == NO_ERROR) { 2114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Ignore routing if device is 0. 2124113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("setParameters(): keyRouting with device %d", device); 213466e8a8fa8d4e6186b72c25cd0289356828177b3Eric Laurent // reset to speaker when disconnecting HDMI to avoid timeout due to write errors 214466e8a8fa8d4e6186b72c25cd0289356828177b3Eric Laurent if ((device == 0) && (mDevices == AudioSystem::DEVICE_OUT_AUX_DIGITAL)) { 215466e8a8fa8d4e6186b72c25cd0289356828177b3Eric Laurent device = AudioSystem::DEVICE_OUT_SPEAKER; 216466e8a8fa8d4e6186b72c25cd0289356828177b3Eric Laurent } 2174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDevices = device; 2184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(device) { 2194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->doRouting(device); 2204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param.remove(key); 2224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2239746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_FM_ENABLED 2244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else { 2254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev key = String8(AudioParameter::keyHandleFm); 2264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.getInt(key, device) == NO_ERROR) { 2274113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("setParameters(): handleFm with device %d", device); 2284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDevices = device; 2294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(device) { 2304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->handleFm(device); 2314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param.remove(key); 2334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 2364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_ERROR; 2384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 2394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2404765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevString8 ALSAStreamOps::getParameters(const String8& keys) 2414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 2424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev AudioParameter param = AudioParameter(keys); 2434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev String8 value; 2444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev String8 key = String8(AudioParameter::keyRouting); 2454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.get(key, value) == NO_ERROR) { 2474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param.addInt(key, (int)mDevices); 2484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else { 2509746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_VOIP_ENABLED 2514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev key = String8(AudioParameter::keyVoipCheck); 2524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.get(key, value) == NO_ERROR) { 2534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((!strncmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL, strlen(SND_USE_CASE_VERB_IP_VOICECALL))) || 2544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (!strncmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP, strlen(SND_USE_CASE_MOD_PLAY_VOIP)))) 2554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param.addInt(key, true); 2564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else 2574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param.addInt(key, false); 2584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2594113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev#endif 2604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 261b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani key = String8(AUDIO_PARAMETER_STREAM_SUP_CHANNELS); 262b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani if (param.get(key, value) == NO_ERROR) { 263b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani EDID_AUDIO_INFO info = { 0 }; 264b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani bool first = true; 265b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani value = String8(); 266b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani if (AudioUtil::getHDMIAudioSinkCaps(&info)) { 267b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani for (int i = 0; i < info.nAudioBlocks && i < MAX_EDID_BLOCKS; i++) { 268b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani String8 append; 269b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani switch (info.AudioBlocksArray[i].nChannels) { 270b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani //Do not handle stereo output in Multi-channel cases 271b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani //Stereo case is handled in normal playback path 272b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani case 6: 273b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani ENUM_TO_STRING(append, AUDIO_CHANNEL_OUT_5POINT1); 274b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani break; 275b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani case 8: 276b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani ENUM_TO_STRING(append, AUDIO_CHANNEL_OUT_7POINT1); 277b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani break; 278b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani default: 279b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani ALOGD("Unsupported number of channels %d", info.AudioBlocksArray[i].nChannels); 280b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani break; 281b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani } 282b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani if (!append.isEmpty()) { 283b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani value += (first ? append : String8("|") + append); 284b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani first = false; 285b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani } 286b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani } 287b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani } else { 288b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani ALOGE("Failed to get HDMI sink capabilities"); 289b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani } 290b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani param.add(key, value); 291b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani } 2924113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("getParameters() %s", param.toString().string()); 2934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return param.toString(); 2944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 2954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevuint32_t ALSAStreamOps::sampleRate() const 2974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 2984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return mHandle->sampleRate; 2994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 3004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// 3024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// Return the number of bytes (not frames) 3034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// 3044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevsize_t ALSAStreamOps::bufferSize() const 3054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 3064113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("bufferSize() returns %d", mHandle->bufferSize); 3074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return mHandle->bufferSize; 3084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 3094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevint ALSAStreamOps::format() const 3114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 3124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int audioSystemFormat; 3134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_pcm_format_t ALSAFormat = mHandle->format; 3154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev switch(ALSAFormat) { 3174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case SNDRV_PCM_FORMAT_S8: 3184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev audioSystemFormat = AudioSystem::PCM_8_BIT; 3194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 3204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::AMR_NB: 3224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::AMR_WB: 3239746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_QCHAT_ENABLED 3244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::EVRC: 3254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::EVRCB: 3264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::EVRCWB: 3274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 3284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev audioSystemFormat = mHandle->format; 3294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 3304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case SNDRV_PCM_FORMAT_S16_LE: 3314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev audioSystemFormat = AudioSystem::PCM_16_BIT; 3324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 3334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev default: 3354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev LOG_FATAL("Unknown AudioSystem bit width %d!", audioSystemFormat); 3364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev audioSystemFormat = AudioSystem::PCM_16_BIT; 3374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 3384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3409efed76df6b7c75d170e8f900f875f4329587719SathishKumar Mani ALOGV("ALSAFormat:0x%x,audioSystemFormat:0x%x",ALSAFormat,audioSystemFormat); 3414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return audioSystemFormat; 3424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 3434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevuint32_t ALSAStreamOps::channels() const 3454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 3464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev unsigned int count = mHandle->channels; 3474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint32_t channels = 0; 3484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mDevices & AudioSystem::DEVICE_OUT_ALL) 3504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev switch(count) { 3514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 4: 3524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev channels |= AudioSystem::CHANNEL_OUT_BACK_LEFT; 3534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev channels |= AudioSystem::CHANNEL_OUT_BACK_RIGHT; 3544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Fall through... 3554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev default: 3564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 2: 3574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev channels |= AudioSystem::CHANNEL_OUT_FRONT_RIGHT; 3584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Fall through... 3594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 1: 3604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev channels |= AudioSystem::CHANNEL_OUT_FRONT_LEFT; 3614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 3624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else 3644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev switch(count) { 3659746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_SSR_ENABLED 3664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // For 5.1 recording 3674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 6 : 3684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev channels |= AudioSystem::CHANNEL_IN_5POINT1; 3694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 3704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Do not fall through... 3714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 3724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev default: 3734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 2: 3744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev channels |= AudioSystem::CHANNEL_IN_RIGHT; 3754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Fall through... 3764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 1: 3774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev channels |= AudioSystem::CHANNEL_IN_LEFT; 3784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 3794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return channels; 3824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 3834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid ALSAStreamOps::close() 3854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 3864113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("close"); 3874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((!strncmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL, strlen(SND_USE_CASE_VERB_IP_VOICECALL))) || 3884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (!strncmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP, strlen(SND_USE_CASE_MOD_PLAY_VOIP)))) { 3894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->mVoipBitRate = 0; 3904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->mVoipStreamCount = 0; 3914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->mALSADevice->close(mHandle); 3934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 3944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// 3964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// Set playback or capture PCM device. It's possible to support audio output 3974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// or input from multiple devices by using the ALSA plugins, but this is 3984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// not supported for simplicity. 3994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// 4004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// The AudioHardwareALSA API does not allow one to set the input routing. 4014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// 4024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// If the "routes" value does not map to a valid device, the default playback 4034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// device is used. 4044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// 4054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t ALSAStreamOps::open(int mode) 4064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 4074113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("open"); 4084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return mParent->mALSADevice->open(mHandle); 4094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 4104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} // namespace androidi_audio_legacy 412