Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bf1c8748 authored by SathishKumar Mani's avatar SathishKumar Mani Committed by Iliyan Malchev
Browse files

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: default avatarIliyan Malchev <malchev@google.com>
parent b357a77d
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -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;
+71 −1
Original line number Diff line number Diff line
@@ -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;
+2 −0
Original line number Diff line number Diff line
@@ -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
+26 −12
Original line number Diff line number Diff line
@@ -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));
            }
        } 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));
                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 {
                       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);
+13 −20
Original line number Diff line number Diff line
@@ -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;
@@ -599,20 +598,6 @@ void switchDevice(alsa_handle_t *handle, uint32_t devices, uint32_t mode)
#endif
    }

    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,