status_t SpeechPhoneCallController::SetTtyCtmMode(const tty_mode_t tty_mode, const audio_mode_t audio_mode)
{
    ALOGD("+%s(), mTty_Ctm = %d, new tty mode = %d, audio_mode = %d", __FUNCTION__, mTty_Ctm, tty_mode, audio_mode);

    if (mTty_Ctm != tty_mode)
    {
        mTty_Ctm = tty_mode;

        SpeechDriverInterface *pSpeechDriver = mSpeechDriverFactory->GetSpeechDriver();
        const bool bt_device_on = android_audio_legacy::AudioSystem::isBluetoothScoDevice((android_audio_legacy::AudioSystem::audio_devices)mAudioResourceManager->getDlOutputDevice());
        if (bt_device_on == false &&
            pSpeechDriver->GetApSideModemStatus(VT_STATUS_MASK) == false &&
            pSpeechDriver->GetApSideModemStatus(SPEECH_STATUS_MASK) == true)
        {
            mAudioResourceManager->EnableAudioLock(AudioResourceManagerInterface::AUDIO_HARDWARE_LOCK, 3000);
            mAudioResourceManager->EnableAudioLock(AudioResourceManagerInterface::AUDIO_STREAMOUT_LOCK, 3000);

            pSpeechDriver->SetUplinkMute(true);
            if (pSpeechDriver->GetApSideModemStatus(TTY_STATUS_MASK) == true)
            {
                pSpeechDriver->TtyCtmOff();
            }

            mAudioResourceManager->StopOutputDevice();
            mAudioResourceManager->StopInputDevice();
            SetTtyInOutDevice(GetRoutingForTty(), mTty_Ctm, audio_mode);
            mAudioResourceManager->StartOutputDevice();
            mAudioResourceManager->StartInputDevice();

            const audio_devices_t output_device = (audio_devices_t)mAudioResourceManager->getDlOutputDevice();
            const audio_devices_t input_device  = (audio_devices_t)mAudioResourceManager->getUlInputDevice();
            pSpeechDriver->SetSpeechMode(input_device, output_device);

            if ((mTty_Ctm != AUD_TTY_OFF) && (mTty_Ctm != AUD_TTY_ERR) &&
                (pSpeechDriver->GetApSideModemStatus(TTY_STATUS_MASK) == false))
            {
                pSpeechDriver->TtyCtmOn(BAUDOT_MODE);
            }
            pSpeechDriver->SetUplinkMute(mMicMute);

            mAudioResourceManager->DisableAudioLock(AudioResourceManagerInterface::AUDIO_STREAMOUT_LOCK);
            mAudioResourceManager->DisableAudioLock(AudioResourceManagerInterface::AUDIO_HARDWARE_LOCK);
        }
    }

    ALOGD("-%s()", __FUNCTION__);
    return NO_ERROR;
}
status_t SpeechPhoneCallController::CloseModemSpeechControlFlow(const audio_mode_t audio_mode)
{
    Mutex::Autolock _l(mLock);

    ALOGD("+%s(), audio_mode = %d", __FUNCTION__, audio_mode);

    const modem_index_t modem_index = mSpeechDriverFactory->GetActiveModemIndex();
    ASSERT((modem_index == MODEM_1 && audio_mode == AUDIO_MODE_IN_CALL) ||
           (modem_index == MODEM_2 && audio_mode == AUDIO_MODE_IN_CALL_2));

    // check VM need close
    SpeechVMRecorder *pSpeechVMRecorder = SpeechVMRecorder::GetInstance();
    if (pSpeechVMRecorder->GetVMRecordStatus() == true)
    {
        ALOGD("%s(), Close VM/EPL record", __FUNCTION__);
        pSpeechVMRecorder->Close();
    }

    // Stop PMIC digital/analog part - downlink
    mAudioResourceManager->StopOutputDevice();

    // Stop Side Tone Filter
    mAudioDigitalInstance->EnableSideToneFilter(false);

    // Stop MODEM_PCM
    mAudioDigitalInstance->SetModemPcmEnable(modem_index, false);

    // Stop PMIC digital/analog part - uplink
    mAudioResourceManager->StopInputDevice();

    // Stop AP side digital part
    CloseModemSpeechDigitalPart(modem_index, (audio_devices_t)mAudioResourceManager->getDlOutputDevice());



    // Get current active speech driver
    SpeechDriverInterface *pSpeechDriver = mSpeechDriverFactory->GetSpeechDriver();

    // check BGS need close
    if (pSpeechDriver->GetApSideModemStatus(BGS_STATUS_MASK) == true)
    {
        pSpeechDriver->BGSoundOff();
    }

    // Speech/VT off
    if (pSpeechDriver->GetApSideModemStatus(VT_STATUS_MASK) == true)
    {
        pSpeechDriver->PCM2WayOff();
        pSpeechDriver->VideoTelephonyOff();
    }
    else if (pSpeechDriver->GetApSideModemStatus(SPEECH_STATUS_MASK) == true)
    {
        if (pSpeechDriver->GetApSideModemStatus(TTY_STATUS_MASK) == true)
        {
            pSpeechDriver->TtyCtmOff();
        }
        pSpeechDriver->SpeechOff();
    }
    else
    {
        ALOGE("%s(), audio_mode = %d, Speech & VT are already closed!!", __FUNCTION__, audio_mode);
        ASSERT(pSpeechDriver->GetApSideModemStatus(VT_STATUS_MASK)     == true ||
               pSpeechDriver->GetApSideModemStatus(SPEECH_STATUS_MASK) == true);
    }

    // AFE_ON = false
    mAudioDigitalInstance->SetAfeEnable(false);

    // recover sampling rate
    mAudioAnalogInstance->SetFrequency(AudioAnalogType::DEVICE_OUT_DAC, 44100);
    mAudioAnalogInstance->SetFrequency(AudioAnalogType::DEVICE_IN_ADC, 44100);

    // disable clock
    SetAfeAnalogClock(false);

    // clean VT status
    if (mVtNeedOn == true)
    {
        ALOGD("%s(), Set mVtNeedOn = false");
        mVtNeedOn = false;
    }

    ALOGD("-%s(), audio_mode = %d", __FUNCTION__, audio_mode);

    return NO_ERROR;
}