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>
diff --git a/alsa_sound/ALSAStreamOps.cpp b/alsa_sound/ALSAStreamOps.cpp
index f38b35e..aafc736 100644
--- a/alsa_sound/ALSAStreamOps.cpp
+++ b/alsa_sound/ALSAStreamOps.cpp
@@ -104,6 +104,11 @@
*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 @@
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 2a08fac..a53f161 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 @@
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 957bf75..932b18f 100644
--- a/alsa_sound/AudioHardwareALSA.h
+++ b/alsa_sound/AudioHardwareALSA.h
@@ -63,6 +63,8 @@
#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 49c0581..64492ba 100644
--- a/alsa_sound/AudioStreamOutALSA.cpp
+++ b/alsa_sound/AudioStreamOutALSA.cpp
@@ -125,22 +125,35 @@
(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 @@
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 3fddd28..18a28d2 100644
--- a/alsa_sound/alsa_default.cpp
+++ b/alsa_sound/alsa_default.cpp
@@ -98,7 +98,6 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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,