diff options
| author | SathishKumar Mani <smani@codeaurora.org> | 2012-09-25 23:34:51 -0700 |
|---|---|---|
| committer | Iliyan Malchev <malchev@google.com> | 2012-10-07 16:45:38 -0700 |
| commit | bf1c87481d62736cab8832e9085c121fbafdbb6b (patch) | |
| tree | 39dba978745f04e7d7f2dd6a59de7a1d38940ec0 | |
| parent | b357a77dc9c72cb6e327e945421f440052233b51 (diff) | |
| download | hardware_qcom_audio-bf1c87481d62736cab8832e9085c121fbafdbb6b.tar.gz hardware_qcom_audio-bf1c87481d62736cab8832e9085c121fbafdbb6b.tar.bz2 hardware_qcom_audio-bf1c87481d62736cab8832e9085c121fbafdbb6b.zip | |
alsa_sound: Add support for multichannel hdmi
- Multichannel audio support for HDMI for AAC
format with 5.1 channels max.
Bug: 7156174
Change-Id: I42e92fa2b14d35a5882cc6d84c6651a6a4d5092a
Signed-off-by: Iliyan Malchev <malchev@google.com>
| -rw-r--r-- | alsa_sound/ALSAStreamOps.cpp | 10 | ||||
| -rw-r--r-- | alsa_sound/AudioHardwareALSA.cpp | 72 | ||||
| -rw-r--r-- | alsa_sound/AudioHardwareALSA.h | 2 | ||||
| -rw-r--r-- | alsa_sound/AudioStreamOutALSA.cpp | 38 | ||||
| -rw-r--r-- | alsa_sound/alsa_default.cpp | 33 |
5 files changed, 122 insertions, 33 deletions
diff --git a/alsa_sound/ALSAStreamOps.cpp b/alsa_sound/ALSAStreamOps.cpp index f38b35e7..aafc7369 100644 --- a/alsa_sound/ALSAStreamOps.cpp +++ b/alsa_sound/ALSAStreamOps.cpp @@ -104,6 +104,11 @@ status_t ALSAStreamOps::set(int *format, *channels = 0; if (mHandle->devices & AudioSystem::DEVICE_OUT_ALL) { switch(mHandle->channels) { + case 6: + case 5: + *channels |= audio_channel_out_mask_from_count(mHandle->channels); + break; + // Do not fall through case 4: *channels |= AudioSystem::CHANNEL_OUT_BACK_LEFT; *channels |= AudioSystem::CHANNEL_OUT_BACK_RIGHT; @@ -348,6 +353,11 @@ uint32_t ALSAStreamOps::channels() const if (mDevices & AudioSystem::DEVICE_OUT_ALL) switch(count) { + case 6: + case 5: + channels |=audio_channel_out_mask_from_count(count); + break; + // Do not fall through case 4: channels |= AudioSystem::CHANNEL_OUT_BACK_LEFT; channels |= AudioSystem::CHANNEL_OUT_BACK_RIGHT; diff --git a/alsa_sound/AudioHardwareALSA.cpp b/alsa_sound/AudioHardwareALSA.cpp index 2a08fac4..a53f1619 100644 --- a/alsa_sound/AudioHardwareALSA.cpp +++ b/alsa_sound/AudioHardwareALSA.cpp @@ -42,6 +42,7 @@ #ifdef QCOM_USBAUDIO_ENABLED #include "AudioUsbALSA.h" #endif +#include "AudioUtil.h" extern "C" { @@ -813,7 +814,76 @@ AudioHardwareALSA::openOutputStream(uint32_t devices, return out; } else #endif - { + if ((flag & AUDIO_OUTPUT_FLAG_DIRECT) && + (devices == AudioSystem::DEVICE_OUT_AUX_DIGITAL)) { + ALOGD("Multi channel PCM"); + alsa_handle_t alsa_handle; + EDID_AUDIO_INFO info = { 0 }; + + alsa_handle.module = mALSADevice; + alsa_handle.devices = devices; + alsa_handle.handle = 0; + alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE; + + if (!AudioUtil::getHDMIAudioSinkCaps(&info)) { + ALOGE("openOutputStream: Failed to get HDMI sink capabilities"); + return NULL; + } + if (0 == *channels) { + alsa_handle.channels = info.AudioBlocksArray[info.nAudioBlocks-1].nChannels; + if (alsa_handle.channels > 6) { + alsa_handle.channels = 6; + } + *channels = audio_channel_out_mask_from_count(alsa_handle.channels); + } else { + alsa_handle.channels = AudioSystem::popCount(*channels); + } + if (6 == alsa_handle.channels) { + alsa_handle.bufferSize = DEFAULT_MULTI_CHANNEL_BUF_SIZE; + } else { + alsa_handle.bufferSize = DEFAULT_BUFFER_SIZE; + } + if (0 == *sampleRate) { + alsa_handle.sampleRate = info.AudioBlocksArray[info.nAudioBlocks-1].nSamplingFreq; + *sampleRate = alsa_handle.sampleRate; + } else { + alsa_handle.sampleRate = *sampleRate; + } + alsa_handle.latency = PLAYBACK_LATENCY; + alsa_handle.rxHandle = 0; + alsa_handle.ucMgr = mUcMgr; + ALOGD("alsa_handle.channels %d alsa_handle.sampleRate %d",alsa_handle.channels,alsa_handle.sampleRate); + + char *use_case; + snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case); + if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) { + strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI2 , sizeof(alsa_handle.useCase)); + } else { + strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_MUSIC2, sizeof(alsa_handle.useCase)); + } + free(use_case); + mDeviceList.push_back(alsa_handle); + ALSAHandleList::iterator it = mDeviceList.end(); + it--; + ALOGD("it->useCase %s", it->useCase); + mALSADevice->route(&(*it), devices, mode()); + if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI2)) { + snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI2 ); + } else { + snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_MUSIC2); + } + ALOGD("channels: %d", AudioSystem::popCount(*channels)); + err = mALSADevice->open(&(*it)); + + if (err) { + ALOGE("Device open failed err:%d",err); + } else { + out = new AudioStreamOutALSA(this, &(*it)); + err = out->set(format, channels, sampleRate, devices); + } + if (status) *status = err; + return out; + } else { alsa_handle_t alsa_handle; unsigned long bufferSize = DEFAULT_BUFFER_SIZE; diff --git a/alsa_sound/AudioHardwareALSA.h b/alsa_sound/AudioHardwareALSA.h index 957bf75e..932b18f2 100644 --- a/alsa_sound/AudioHardwareALSA.h +++ b/alsa_sound/AudioHardwareALSA.h @@ -63,6 +63,8 @@ class AudioHardwareALSA; #define RECORD_LATENCY 96000 #define VOICE_LATENCY 85333 #define DEFAULT_BUFFER_SIZE 4096 +//4032 = 336(kernel buffer size) * 2(bytes pcm_16) * 6(number of channels) +#define DEFAULT_MULTI_CHANNEL_BUF_SIZE 4032 #define DEFAULT_VOICE_BUFFER_SIZE 2048 #define PLAYBACK_LOW_LATENCY_BUFFER_SIZE 1024 #define PLAYBACK_LOW_LATENCY 22000 diff --git a/alsa_sound/AudioStreamOutALSA.cpp b/alsa_sound/AudioStreamOutALSA.cpp index 49c05813..64492bac 100644 --- a/alsa_sound/AudioStreamOutALSA.cpp +++ b/alsa_sound/AudioStreamOutALSA.cpp @@ -125,22 +125,35 @@ ssize_t AudioStreamOutALSA::write(const void *buffer, size_t bytes) (strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) { mParent->mLock.lock(); + ALOGD("mHandle->useCase: %s", mHandle->useCase); snd_use_case_get(mHandle->ucMgr, "_verb", (const char **)&use_case); if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) { - if(!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)){ - strlcpy(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL,sizeof(mHandle->useCase)); - } else if (mHandle->isDeepbufferOutput){ - strlcpy(mHandle->useCase, SND_USE_CASE_VERB_HIFI, sizeof(mHandle->useCase)); - } else { - strlcpy(mHandle->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC, sizeof(mHandle->useCase)); + if(!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP)){ + strlcpy(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL, + sizeof(SND_USE_CASE_VERB_IP_VOICECALL)); + } else if(!strcmp(mHandle->useCase,SND_USE_CASE_MOD_PLAY_MUSIC2)) { + strlcpy(mHandle->useCase, SND_USE_CASE_VERB_HIFI2, + sizeof(SND_USE_CASE_MOD_PLAY_MUSIC2)); + } else if (!strcmp(mHandle->useCase,SND_USE_CASE_MOD_PLAY_MUSIC)){ + strlcpy(mHandle->useCase, SND_USE_CASE_VERB_HIFI, + sizeof(SND_USE_CASE_MOD_PLAY_MUSIC)); + } else if(!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC)) { + strlcpy(mHandle->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC, + sizeof(SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC)); } } else { - if(!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP)) { - strlcpy(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP,sizeof(mHandle->useCase)); - } else if (mHandle->isDeepbufferOutput){ - strlcpy(mHandle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC, sizeof(mHandle->useCase)); - } else { - strlcpy(mHandle->useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC, sizeof(mHandle->useCase)); + if(!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)){ + strlcpy(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP, + sizeof(SND_USE_CASE_MOD_PLAY_VOIP)); + } else if(!strcmp(mHandle->useCase,SND_USE_CASE_VERB_HIFI2)) { + strlcpy(mHandle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC2, + sizeof(SND_USE_CASE_MOD_PLAY_MUSIC2)); + } else if (!strcmp(mHandle->useCase,SND_USE_CASE_VERB_HIFI)){ + strlcpy(mHandle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC, + sizeof(SND_USE_CASE_MOD_PLAY_MUSIC)); + } else if(!strcmp(mHandle->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) { + strlcpy(mHandle->useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC, + sizeof(SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC)); } } free(use_case); @@ -170,6 +183,7 @@ ssize_t AudioStreamOutALSA::write(const void *buffer, size_t bytes) mHandle->module->route(mHandle, mDevices , mParent->mode()); } if (!strcmp(mHandle->useCase, SND_USE_CASE_VERB_HIFI) || + !strcmp(mHandle->useCase, SND_USE_CASE_VERB_HIFI2) || !strcmp(mHandle->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC) || !strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) { snd_use_case_set(mHandle->ucMgr, "_verb", mHandle->useCase); diff --git a/alsa_sound/alsa_default.cpp b/alsa_sound/alsa_default.cpp index 3fddd282..18a28d29 100644 --- a/alsa_sound/alsa_default.cpp +++ b/alsa_sound/alsa_default.cpp @@ -98,7 +98,6 @@ static uint32_t mDevSettingsFlag = TTY_OFF | DMIC_FLAG; static uint32_t mDevSettingsFlag = TTY_OFF; #endif static int btsco_samplerate = 8000; -static bool pflag = false; static ALSAUseCaseList mUseCaseList; static void *csd_handle; @@ -374,8 +373,8 @@ status_t setSoftwareParams(alsa_handle_t *handle) params->start_threshold = periodSize/2; params->stop_threshold = INT_MAX; } else { - params->avail_min = periodSize/2; - params->start_threshold = channels * (periodSize/4); + params->avail_min = periodSize/(channels * 2); + params->start_threshold = periodSize/(channels * 2); params->stop_threshold = INT_MAX; } params->silence_threshold = 0; @@ -581,7 +580,7 @@ void switchDevice(alsa_handle_t *handle, uint32_t devices, uint32_t mode) rx_dev_id = snd_use_case_get(handle->ucMgr, ident, NULL); if (((rx_dev_id == DEVICE_SPEAKER_MONO_RX_ACDB_ID ) || (rx_dev_id == DEVICE_SPEAKER_STEREO_RX_ACDB_ID )) - && tx_dev_id == DEVICE_HANDSET_TX_ACDB_ID) { + && tx_dev_id == DEVICE_HANDSET_TX_ACDB_ID) { tx_dev_id = DEVICE_SPEAKER_TX_ACDB_ID; } @@ -600,20 +599,6 @@ void switchDevice(alsa_handle_t *handle, uint32_t devices, uint32_t mode) } if (rxDevice != NULL) { - if (pflag && (((!strncmp(rxDevice, DEVICE_SPEAKER_HEADSET, strlen(DEVICE_SPEAKER_HEADSET))) && - ((!strncmp(curRxUCMDevice, DEVICE_HEADPHONES, strlen(DEVICE_HEADPHONES))) || - (!strncmp(curRxUCMDevice, DEVICE_HEADSET, strlen(DEVICE_HEADSET))))) || - (((!strncmp(curRxUCMDevice, DEVICE_SPEAKER_HEADSET, strlen(DEVICE_SPEAKER_HEADSET))) && - ((!strncmp(rxDevice, DEVICE_HEADPHONES, strlen(DEVICE_HEADPHONES))) || - (!strncmp(rxDevice, DEVICE_HEADSET, strlen(DEVICE_HEADSET))))))) && - ((!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI, strlen(SND_USE_CASE_VERB_HIFI))) || - (!strncmp(handle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC, strlen(SND_USE_CASE_MOD_PLAY_MUSIC))))) { - s_open(handle); - pflag = false; - } - } - - if (rxDevice != NULL) { free(rxDevice); rxDevice = NULL; } @@ -672,8 +657,10 @@ static status_t s_open(alsa_handle_t *handle) flags |= PCM_MMAP; flags |= DEBUG_ON; } else if ((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI)) || + (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI2)) || (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) || (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC)) || + (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC2)) || (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC))) { ALOGV("Music case"); flags = PCM_OUT; @@ -683,18 +670,20 @@ static status_t s_open(alsa_handle_t *handle) if (handle->channels == 1) { flags |= PCM_MONO; } -#ifdef QCOM_SSR_ENABLED else if (handle->channels == 4 ) { flags |= PCM_QUAD; } else if (handle->channels == 6 ) { +#ifdef QCOM_SSR_ENABLED if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC)) || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) { flags |= PCM_QUAD; } else { flags |= PCM_5POINT1; } - } +#else + flags |= PCM_5POINT1; #endif + } else { flags |= PCM_STEREO; } @@ -1198,6 +1187,8 @@ int getUseCaseType(const char *useCase) ALOGD("use case is %s\n", useCase); if (!strncmp(useCase, SND_USE_CASE_VERB_HIFI, MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI)) || + !strncmp(useCase, SND_USE_CASE_VERB_HIFI2, + MAX_LEN(useCase, SND_USE_CASE_VERB_HIFI2)) || !strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC, MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) || !strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER, @@ -1210,6 +1201,8 @@ int getUseCaseType(const char *useCase) MAX_LEN(useCase,SND_USE_CASE_VERB_DIGITAL_RADIO)) || !strncmp(useCase, SND_USE_CASE_MOD_PLAY_MUSIC, MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_MUSIC)) || + !strncmp(useCase, SND_USE_CASE_MOD_PLAY_MUSIC2, + MAX_LEN(useCase, SND_USE_CASE_MOD_PLAY_MUSIC2)) || !strncmp(useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC, MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC)) || !strncmp(useCase, SND_USE_CASE_MOD_PLAY_MUSIC2, |
