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/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;