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 if (mHandle->devices & AudioSystem::DEVICE_OUT_ALL) { 10561f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent switch(*channels) { 10661f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent case AUDIO_CHANNEL_OUT_5POINT1: // 5.0 10761f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent case (AUDIO_CHANNEL_OUT_QUAD | AUDIO_CHANNEL_OUT_FRONT_CENTER): // 5.1 10861f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent case AUDIO_CHANNEL_OUT_QUAD: 10961f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent case AUDIO_CHANNEL_OUT_STEREO: 11061f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent case AUDIO_CHANNEL_OUT_MONO: 111bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani break; 1124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev default: 11361f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent *channels = AUDIO_CHANNEL_OUT_STEREO; 11461f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent return BAD_VALUE; 1154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 11761f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent switch(*channels) { 1189746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_SSR_ENABLED 1194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // For 5.1 recording 12061f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent case AudioSystem::CHANNEL_IN_5POINT1: 1214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 1224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Do not fall through... 12361f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent case AUDIO_CHANNEL_IN_MONO: 12461f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent case AUDIO_CHANNEL_IN_STEREO: 12561f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent case AUDIO_CHANNEL_IN_FRONT_BACK: 1264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 12761f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent default: 12861f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent *channels = AUDIO_CHANNEL_IN_MONO; 12961f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent return BAD_VALUE; 1304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (rate && *rate > 0) { 1354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mHandle->sampleRate != *rate) 1364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return BAD_VALUE; 1374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if (rate) { 1384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *rate = mHandle->sampleRate; 1394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_pcm_format_t iformat = mHandle->format; 1424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (format) { 1444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev switch(*format) { 1454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::FORMAT_DEFAULT: 1464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::PCM_16_BIT: 1494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev iformat = SNDRV_PCM_FORMAT_S16_LE; 1504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::AMR_NB: 1524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::AMR_WB: 1539746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_QCHAT_ENABLED 1544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::EVRC: 1554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::EVRCB: 1564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::EVRCWB: 1574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 1584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev iformat = *format; 1594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::PCM_8_BIT: 1624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev iformat = SNDRV_PCM_FORMAT_S8; 1634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev default: 1664113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("Unknown PCM format %i. Forcing default", *format); 1674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mHandle->format != iformat) 1714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return BAD_VALUE; 1724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev switch(iformat) { 1744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case SNDRV_PCM_FORMAT_S16_LE: 1754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *format = AudioSystem::PCM_16_BIT; 1764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case SNDRV_PCM_FORMAT_S8: 1784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *format = AudioSystem::PCM_8_BIT; 1794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev default: 1814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_ERROR; 1864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 1874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t ALSAStreamOps::setParameters(const String8& keyValuePairs) 1894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 1904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev AudioParameter param = AudioParameter(keyValuePairs); 1914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev String8 key = String8(AudioParameter::keyRouting); 1924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int device; 19374060dee8c9a414ad0345176e2422de18a4ff183ty.lee 19474060dee8c9a414ad0345176e2422de18a4ff183ty.lee#ifdef SEPERATED_AUDIO_INPUT 19574060dee8c9a414ad0345176e2422de18a4ff183ty.lee String8 key_input = String8(AudioParameter::keyInputSource); 19674060dee8c9a414ad0345176e2422de18a4ff183ty.lee int source; 19774060dee8c9a414ad0345176e2422de18a4ff183ty.lee 19874060dee8c9a414ad0345176e2422de18a4ff183ty.lee if (param.getInt(key_input, source) == NO_ERROR) { 19974060dee8c9a414ad0345176e2422de18a4ff183ty.lee ALOGD("setParameters(), input_source = %d", source); 20074060dee8c9a414ad0345176e2422de18a4ff183ty.lee mParent->mALSADevice->setInput(source); 20174060dee8c9a414ad0345176e2422de18a4ff183ty.lee param.remove(key_input); 20274060dee8c9a414ad0345176e2422de18a4ff183ty.lee } 20374060dee8c9a414ad0345176e2422de18a4ff183ty.lee#endif 20474060dee8c9a414ad0345176e2422de18a4ff183ty.lee 2054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.getInt(key, device) == NO_ERROR) { 2064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Ignore routing if device is 0. 2072c79891211108cd8157124c1b6f9d393729602ffsamin.ryu ALOGD("setParameters(): keyRouting with device 0x%x", device); 208466e8a8fa8d4e6186b72c25cd0289356828177b3Eric Laurent // reset to speaker when disconnecting HDMI to avoid timeout due to write errors 209466e8a8fa8d4e6186b72c25cd0289356828177b3Eric Laurent if ((device == 0) && (mDevices == AudioSystem::DEVICE_OUT_AUX_DIGITAL)) { 210466e8a8fa8d4e6186b72c25cd0289356828177b3Eric Laurent device = AudioSystem::DEVICE_OUT_SPEAKER; 211466e8a8fa8d4e6186b72c25cd0289356828177b3Eric Laurent } 2122c79891211108cd8157124c1b6f9d393729602ffsamin.ryu if (device) 2132c79891211108cd8157124c1b6f9d393729602ffsamin.ryu mDevices = device; 2142c79891211108cd8157124c1b6f9d393729602ffsamin.ryu else 2152c79891211108cd8157124c1b6f9d393729602ffsamin.ryu ALOGV("must not change mDevices to 0"); 2162c79891211108cd8157124c1b6f9d393729602ffsamin.ryu 2174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(device) { 2184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->doRouting(device); 2194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param.remove(key); 2214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2229746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_FM_ENABLED 2234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else { 2244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev key = String8(AudioParameter::keyHandleFm); 2254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.getInt(key, device) == NO_ERROR) { 2264113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("setParameters(): handleFm with device %d", device); 2274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDevices = device; 2284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(device) { 2294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->handleFm(device); 2304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param.remove(key); 2324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 2354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_ERROR; 2374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 2384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2394765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevString8 ALSAStreamOps::getParameters(const String8& keys) 2404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 2414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev AudioParameter param = AudioParameter(keys); 2424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev String8 value; 2434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev String8 key = String8(AudioParameter::keyRouting); 2444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.get(key, value) == NO_ERROR) { 2464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param.addInt(key, (int)mDevices); 2474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else { 2499746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_VOIP_ENABLED 2504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev key = String8(AudioParameter::keyVoipCheck); 2514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.get(key, value) == NO_ERROR) { 2524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((!strncmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL, strlen(SND_USE_CASE_VERB_IP_VOICECALL))) || 2534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (!strncmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP, strlen(SND_USE_CASE_MOD_PLAY_VOIP)))) 2544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param.addInt(key, true); 2554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else 2564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param.addInt(key, false); 2574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2584113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev#endif 2594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 260b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani key = String8(AUDIO_PARAMETER_STREAM_SUP_CHANNELS); 261b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani if (param.get(key, value) == NO_ERROR) { 262b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani EDID_AUDIO_INFO info = { 0 }; 263b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani bool first = true; 264b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani value = String8(); 265b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani if (AudioUtil::getHDMIAudioSinkCaps(&info)) { 266b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani for (int i = 0; i < info.nAudioBlocks && i < MAX_EDID_BLOCKS; i++) { 267b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani String8 append; 268b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani switch (info.AudioBlocksArray[i].nChannels) { 269b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani //Do not handle stereo output in Multi-channel cases 270b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani //Stereo case is handled in normal playback path 271b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani case 6: 272b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani ENUM_TO_STRING(append, AUDIO_CHANNEL_OUT_5POINT1); 273b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani break; 274b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani case 8: 275b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani ENUM_TO_STRING(append, AUDIO_CHANNEL_OUT_7POINT1); 276b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani break; 277b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani default: 278b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani ALOGD("Unsupported number of channels %d", info.AudioBlocksArray[i].nChannels); 279b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani break; 280b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani } 281b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani if (!append.isEmpty()) { 282b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani value += (first ? append : String8("|") + append); 283b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani first = false; 284b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani } 285b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani } 286b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani } else { 287b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani ALOGE("Failed to get HDMI sink capabilities"); 288b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani } 289b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani param.add(key, value); 290b357a77dc9c72cb6e327e945421f440052233b51SathishKumar Mani } 2914113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("getParameters() %s", param.toString().string()); 2924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return param.toString(); 2934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 2944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevuint32_t ALSAStreamOps::sampleRate() const 2964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 2974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return mHandle->sampleRate; 2984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 2994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// 3014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// Return the number of bytes (not frames) 3024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// 3034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevsize_t ALSAStreamOps::bufferSize() const 3044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 3054113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("bufferSize() returns %d", mHandle->bufferSize); 3064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return mHandle->bufferSize; 3074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 3084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevint ALSAStreamOps::format() const 3104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 3114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int audioSystemFormat; 3124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_pcm_format_t ALSAFormat = mHandle->format; 3144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev switch(ALSAFormat) { 3164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case SNDRV_PCM_FORMAT_S8: 3174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev audioSystemFormat = AudioSystem::PCM_8_BIT; 3184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 3194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::AMR_NB: 3214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::AMR_WB: 3229746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_QCHAT_ENABLED 3234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::EVRC: 3244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::EVRCB: 3254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::EVRCWB: 3264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 3274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev audioSystemFormat = mHandle->format; 3284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 3294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case SNDRV_PCM_FORMAT_S16_LE: 3304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev audioSystemFormat = AudioSystem::PCM_16_BIT; 3314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 3324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev default: 3344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev LOG_FATAL("Unknown AudioSystem bit width %d!", audioSystemFormat); 3354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev audioSystemFormat = AudioSystem::PCM_16_BIT; 3364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 3374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3399efed76df6b7c75d170e8f900f875f4329587719SathishKumar Mani ALOGV("ALSAFormat:0x%x,audioSystemFormat:0x%x",ALSAFormat,audioSystemFormat); 3404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return audioSystemFormat; 3414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 3424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevuint32_t ALSAStreamOps::channels() const 3444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 34561f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent return mHandle->channelMask; 3464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 3474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid ALSAStreamOps::close() 3494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 3504113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("close"); 3514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((!strncmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL, strlen(SND_USE_CASE_VERB_IP_VOICECALL))) || 3524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (!strncmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP, strlen(SND_USE_CASE_MOD_PLAY_VOIP)))) { 3534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->mVoipBitRate = 0; 3544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->mVoipStreamCount = 0; 3554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mParent->mALSADevice->close(mHandle); 3574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 3584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// 3604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// Set playback or capture PCM device. It's possible to support audio output 3614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// or input from multiple devices by using the ALSA plugins, but this is 3624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// not supported for simplicity. 3634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// 3644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// The AudioHardwareALSA API does not allow one to set the input routing. 3654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// 3664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// If the "routes" value does not map to a valid device, the default playback 3674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// device is used. 3684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// 3694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t ALSAStreamOps::open(int mode) 3704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 3714113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("open"); 3724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return mParent->mALSADevice->open(mHandle); 3734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 3744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} // namespace androidi_audio_legacy 376