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

Commit 13f26e89 authored by Alain Vongsouvanh's avatar Alain Vongsouvanh
Browse files

audio: hal: add customized external smart pa code

add customized external smart pa control code

Change-Id: I667648a98f887bc488827fada6a00f9f987ff513
parent 122b241e
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -93,6 +93,12 @@ LOCAL_C_INCLUDES += \
	$(LOCAL_PATH)/voice_extn \
	external/expat/lib

ifeq ($(strip $(AUDIO_FEATURE_ENABLED_SMART_PA_TFA_98XX)),true)
    LOCAL_SHARED_LIBRARIES += libexTfa98xx
    LOCAL_CFLAGS += -DSMART_PA_TFA_98XX_SUPPORTED
    LOCAL_SRC_FILES += audio_extn/tfa_98xx.c
endif

ifeq ($(strip $(AUDIO_FEATURE_ENABLED_MULTI_VOICE_SESSIONS)),true)
    LOCAL_CFLAGS += -DMULTI_VOICE_SESSION_ENABLED
    LOCAL_SRC_FILES += voice_extn/voice_extn.c
+4 −0
Original line number Diff line number Diff line
@@ -57,6 +57,8 @@ void audio_extn_spkr_prot_calib_cancel(void *adev);
#define audio_extn_hfp_is_active(adev)                  (0)
#define audio_extn_hfp_get_usecase()                    (-1)
#define audio_extn_hfp_set_parameters(adev, params)     (0)
#define audio_extn_hfp_set_mic_mute(adev, state)        (0)

#else
bool audio_extn_hfp_is_active(struct audio_device *adev);

@@ -64,6 +66,8 @@ audio_usecase_t audio_extn_hfp_get_usecase();

void audio_extn_hfp_set_parameters(struct audio_device *adev,
                                    struct str_parms *parms);
int audio_extn_hfp_set_mic_mute(struct audio_device *adev, bool state);

#endif

#ifndef SOUND_TRIGGER_ENABLED
+162 −16
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include "platform_api.h"
#include <stdlib.h>
#include <cutils/str_parms.h>
#include "audio_extn/tfa_98xx.h"

#define AUDIO_PARAMETER_HFP_ENABLE            "hfp_enable"
#define AUDIO_PARAMETER_HFP_SET_SAMPLING_RATE "hfp_set_sampling_rate"
@@ -34,6 +35,10 @@
#define AUDIO_PARAMETER_HFP_VOL_MIXER_CTL     "hfp_vol_mixer_ctl"
#define AUDIO_PARAMATER_HFP_VALUE_MAX         128

#define AUDIO_PARAMETER_KEY_HFP_MIC_VOLUME "hfp_mic_volume"
#define PLAYBACK_VOLUME_MAX 0x2000
#define CAPTURE_VOLUME_DEFAULT                (15.0)

static int32_t start_hfp(struct audio_device *adev,
                               struct str_parms *parms);

@@ -45,8 +50,10 @@ struct hfp_module {
    struct pcm *hfp_pcm_rx;
    struct pcm *hfp_pcm_tx;
    float  hfp_volume;
    float  mic_volume;
    char   hfp_vol_mixer_ctl[AUDIO_PARAMATER_HFP_VALUE_MAX];
    bool   is_hfp_running;
    bool   mic_mute;
    audio_usecase_t ucid;
};

@@ -56,8 +63,10 @@ static struct hfp_module hfpmod = {
    .hfp_pcm_rx = NULL,
    .hfp_pcm_tx = NULL,
    .hfp_volume = 0,
    .mic_volume = CAPTURE_VOLUME_DEFAULT,
    .hfp_vol_mixer_ctl = {0, },
    .is_hfp_running = 0,
    .mic_mute = 0,
    .ucid = USECASE_AUDIO_HFP_SCO,
};
static struct pcm_config pcm_config_hfp = {
@@ -120,6 +129,115 @@ static int32_t hfp_set_volume(struct audio_device *adev, float value)
    return ret;
}


/*Set mic volume to value.
*
* This interface is used for mic volume control, set mic volume as value(range 0 ~ 15).
*/
static int hfp_set_mic_volume(struct audio_device *adev, float value)
{
    int volume, ret = 0;
    char mixer_ctl_name[128];
    struct mixer_ctl *ctl;
    int pcm_device_id = HFP_ASM_RX_TX;

    if (!hfpmod.is_hfp_running) {
        ALOGE("%s: HFP not active, ignoring set_hfp_mic_volume call", __func__);
        return -EIO;
    }

    if (value < 0.0) {
        ALOGW("%s: (%f) Under 0.0, assuming 0.0\n", __func__, value);
        value = 0.0;
    } else if (value > CAPTURE_VOLUME_DEFAULT) {
        value = CAPTURE_VOLUME_DEFAULT;
        ALOGW("%s: Volume brought within range (%f)\n", __func__, value);
    }

    value = value / CAPTURE_VOLUME_DEFAULT;
    memset(mixer_ctl_name, 0, sizeof(mixer_ctl_name));
    snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
             "Playback %d Volume", pcm_device_id);
    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
    if (!ctl) {
        ALOGE("%s: Could not get ctl for mixer cmd - %s",
              __func__, mixer_ctl_name);
        return -EINVAL;
    }
    volume = (int)(value * PLAYBACK_VOLUME_MAX);

    ALOGD("%s: Setting volume to %d (%s)\n", __func__, volume, mixer_ctl_name);
    if (mixer_ctl_set_value(ctl, 0, volume) < 0) {
        ALOGE("%s: Couldn't set HFP Volume: [%d]", __func__, volume);
        return -EINVAL;
    }

    return ret;
}

static float hfp_get_mic_volume(struct audio_device *adev)
{
    int volume, ret = 0;
    char mixer_ctl_name[128];
    struct mixer_ctl *ctl;
    int pcm_device_id = HFP_ASM_RX_TX;
    float value = 0.0;

    if (!hfpmod.is_hfp_running) {
        ALOGE("%s: HFP not active, ignoring set_hfp_mic_volume call", __func__);
        return -EIO;
    }

    memset(mixer_ctl_name, 0, sizeof(mixer_ctl_name));
    snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
             "Playback %d Volume", pcm_device_id);
    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
    if (!ctl) {
        ALOGE("%s: Could not get ctl for mixer cmd - %s",
              __func__, mixer_ctl_name);
        return -EINVAL;
    }

    volume = mixer_ctl_get_value(ctl, 0);
    if ( volume < 0) {
        ALOGE("%s: Couldn't set HFP Volume: [%d]", __func__, volume);
        return -EINVAL;
    }
    ALOGD("%s: getting mic volume %d \n", __func__, volume);

    value = (volume / PLAYBACK_VOLUME_MAX) * CAPTURE_VOLUME_DEFAULT;
    if (value < 0.0) {
        ALOGW("%s: (%f) Under 0.0, assuming 0.0\n", __func__, value);
        value = 0.0;
    } else if (value > CAPTURE_VOLUME_DEFAULT) {
        value = CAPTURE_VOLUME_DEFAULT;
        ALOGW("%s: Volume brought within range (%f)\n", __func__, value);
    }

    return value;
}

/*Set mic mute state.
*
* This interface is used for mic mute state control
*/
int audio_extn_hfp_set_mic_mute(struct audio_device *adev, bool state)
{
    int rc = 0;

    if (state == hfpmod.mic_mute)
        return rc;

    if (state == true) {
        hfpmod.mic_volume = hfp_get_mic_volume(adev);
    }
    rc = hfp_set_mic_volume(adev, (state == true) ? 0.0 : hfpmod.mic_volume);
    adev->voice.mic_mute = state;
    hfpmod.mic_mute = state;
    ALOGD("%s: Setting mute state %d, rc %d\n", __func__, state, rc);
    return rc;
}

static int32_t start_hfp(struct audio_device *adev,
                         struct str_parms *parms __unused)
{
@@ -170,6 +288,8 @@ static int32_t start_hfp(struct audio_device *adev,
    }
    ALOGD("%s: Opening PCM capture device card_id(%d) device_id(%d)",
          __func__, adev->snd_card, pcm_dev_tx_id);

    if (audio_extn_tfa_98xx_is_supported() == false) {
        hfpmod.hfp_pcm_rx = pcm_open(adev->snd_card,
                                       pcm_dev_rx_id,
                                       PCM_OUT, &pcm_config_hfp);
@@ -178,6 +298,7 @@ static int32_t start_hfp(struct audio_device *adev,
            ret = -EIO;
            goto exit;
        }
    }
    hfpmod.hfp_sco_tx = pcm_open(adev->snd_card,
                                  pcm_dev_asm_tx_id,
                                  PCM_IN, &pcm_config_hfp);
@@ -188,6 +309,8 @@ static int32_t start_hfp(struct audio_device *adev,
    }
    ALOGV("%s: Opening PCM capture device card_id(%d) device_id(%d)",
          __func__, adev->snd_card, pcm_dev_tx_id);

    if (audio_extn_tfa_98xx_is_supported() == false) {
        hfpmod.hfp_pcm_tx = pcm_open(adev->snd_card,
                                       pcm_dev_tx_id,
                                       PCM_IN, &pcm_config_hfp);
@@ -196,14 +319,23 @@ static int32_t start_hfp(struct audio_device *adev,
            ret = -EIO;
            goto exit;
        }
    }
    pcm_start(hfpmod.hfp_sco_rx);
    pcm_start(hfpmod.hfp_sco_tx);
    if (audio_extn_tfa_98xx_is_supported() == false) {
        pcm_start(hfpmod.hfp_pcm_rx);
        pcm_start(hfpmod.hfp_pcm_tx);
    }

    audio_extn_tfa_98xx_enable_speaker();

    hfpmod.is_hfp_running = true;
    hfp_set_volume(adev, hfpmod.hfp_volume);

    /* Set mic volume by mute status, we don't provide set mic volume in phone app, only
    provide mute and unmute. */
    audio_extn_hfp_set_mic_mute(adev, adev->mic_muted);

    ALOGD("%s: exit: status(%d)", __func__, ret);
    return 0;

@@ -349,6 +481,20 @@ void audio_extn_hfp_set_parameters(struct audio_device *adev, struct str_parms *
        ALOGD("%s: set_hfp_volume usecase, Vol: [%f]", __func__, vol);
        hfp_set_volume(adev, vol);
    }

    memset(value, 0, sizeof(value));
    ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_HFP_MIC_VOLUME,
                            value, sizeof(value));
    if (ret >= 0) {
        if (sscanf(value, "%f", &vol) != 1){
            ALOGE("%s: error in retrieving hfp mic volume", __func__);
            ret = -EIO;
            goto exit;
        }
        ALOGD("%s: set_hfp_mic_volume usecase, Vol: [%f]", __func__, vol);
        hfp_set_mic_volume(adev, vol);
    }

exit:
    ALOGV("%s Exit",__func__);
}
+516 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2013-2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "tfa_98xx"
/*#define LOG_NDEBUG 0*/
#include <cutils/log.h>

#include <stdlib.h>
#include <audio_hw.h>
#include <dlfcn.h>
#include "audio_extn.h"
#include <platform.h>

#define LIB_SPEAKER_BUNDLE "/system/lib/libexTfa98xx.so"


enum exTfa98xx_Audio_Mode
{
    Audio_Mode_None = -1,
    Audio_Mode_Music_Normal,
    Audio_Mode_Hfp_Client,
    Audio_Mode_Voice,
    Audio_Mode_Hs_Hfp,
    Audio_Mode_Max
};
typedef enum exTfa98xx_Audio_Mode exTfa98xx_audio_mode_t;

enum exTfa98xx_Func_Mode
{
    Func_Mode_None = -1,
    Func_Mode_Speaker,
    Func_Mode_BT
};
typedef enum exTfa98xx_Func_Mode exTfa98xx_func_mode_t;

#define I2S_CLOCK_ENABLE        1
#define I2S_CLOCK_DISABLE       0

exTfa98xx_audio_mode_t current_audio_mode = Audio_Mode_None;

typedef int (*set_speaker_on_t)(exTfa98xx_audio_mode_t);
typedef int (*set_speaker_off_t)(void);
typedef int (*set_speaker_calibration_t)(int);
typedef void (*set_speaker_volume_step_t)(int, int);


struct speaker_data {
    struct audio_device *adev;
    void *speaker_bundle;
    set_speaker_on_t set_speaker_on;
    set_speaker_off_t set_speaker_off;
    set_speaker_calibration_t set_speaker_calibration;
    set_speaker_volume_step_t set_speaker_volume_step;
    int ref_cnt[Audio_Mode_Max];
    int route_cnt[Audio_Mode_Max];
    bool update_ref_cnt;
};

struct speaker_data *tfa98xx_speaker_data = NULL;

static struct speaker_data* open_speaker_bundle()
{
    struct speaker_data *sd = calloc(1, sizeof(struct speaker_data));

    sd->speaker_bundle = dlopen(LIB_SPEAKER_BUNDLE, RTLD_NOW);
    if (sd->speaker_bundle == NULL) {
        ALOGE("%s: DLOPEN failed for %s", __func__, LIB_SPEAKER_BUNDLE);
        goto error;
    } else {
        ALOGV("%s: DLOPEN successful for %s", __func__, LIB_SPEAKER_BUNDLE);

        sd->set_speaker_on = (set_speaker_on_t)dlsym(sd->speaker_bundle,
                                             "exTfa98xx_speakeron");
        if (sd->set_speaker_on == NULL) {
            ALOGE("%s: dlsym error %s for exTfa98xx_speakeron", __func__,
                  dlerror());
            goto error;
        }
        sd->set_speaker_off = (set_speaker_off_t)dlsym(sd->speaker_bundle,
                                             "exTfa98xx_speakeroff");
        if (sd->set_speaker_off == NULL) {
            ALOGE("%s: dlsym error %s for exTfa98xx_speakeroff", __func__,
                  dlerror());
            goto error;
        }
        sd->set_speaker_volume_step = (set_speaker_volume_step_t)dlsym(sd->speaker_bundle,
                                             "exTfa98xx_setvolumestep");
        if (sd->set_speaker_volume_step == NULL) {
            ALOGE("%s: dlsym error %s for exTfa98xx_setvolumestep",
                  __func__, dlerror());
            goto error;
        }
        sd->set_speaker_calibration = (set_speaker_calibration_t)dlsym(sd->speaker_bundle,
                                             "exTfa98xx_calibration");
        if (sd->set_speaker_calibration == NULL) {
            ALOGE("%s: dlsym error %s for exTfa98xx_calibration",
                  __func__, dlerror());
            goto error;
        }
    }
    return sd;

error:
    free(sd);
    return 0;
}

static void close_speaker_bundle(struct speaker_data *sd)
{
    if (sd != NULL) {
        dlclose(sd->speaker_bundle);
        free(sd);
        sd = NULL;
    }
}

static int adev_i2s_clock_operation(int enable, struct audio_device *adev, char *paths)
{
    int ret = -1;

    ALOGD("%s: mixer paths is: %s, enable: %d\n", __func__, paths, enable);
    if(I2S_CLOCK_ENABLE == enable) {
        ret = audio_route_apply_and_update_path(adev->audio_route, paths);
        if(ret) {
            ALOGE("%s: audio_route_apply_and_update_path return %d\n", __func__, ret);
            return ret;
        }
    } else {
        ret = audio_route_reset_and_update_path(adev->audio_route, paths);
        if(ret) {
            ALOGE("%s: audio_route_reset_and_update_path return %d\n", __func__, ret);
            return ret;
        }
    }
    return 0;
}

static int tfa_98xx_set_audio_mode(int enable, struct audio_device *adev, exTfa98xx_audio_mode_t audio_mode)
{
    char paths[32] = "init_smart_pa";

    switch(audio_mode) {
        case Audio_Mode_Music_Normal:
            strcat(paths, " music");
            break;
        case Audio_Mode_Voice:
        case Audio_Mode_Hfp_Client:
        case Audio_Mode_Hs_Hfp:
            strcat(paths, " voice");
            break;
        default:
            ALOGE("%s: function %d not support!\n",__func__, audio_mode);
            return -EINVAL;
    }

    ALOGV("%s: mixer paths is: %s, enable: %d\n", __func__, paths, enable);
    adev_i2s_clock_operation(enable, adev, paths);
    return 0;

}

static exTfa98xx_audio_mode_t tfa_98xx_get_audio_mode(struct speaker_data *data)
{
    exTfa98xx_audio_mode_t tfa_98xx_audio_mode = Audio_Mode_None;
    struct listnode *node;
    struct audio_usecase *usecase;
    audio_mode_t mode = data->adev->mode;
    int i = 0;

    ALOGV("%s: enter\n", __func__);

    for (i = 0; i < Audio_Mode_Max; i++)
        data->route_cnt[i] = 0;

    list_for_each(node, &data->adev->usecase_list) {
        usecase = node_to_item(node, struct audio_usecase, list);
        if (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
            if(data->adev->snd_dev_ref_cnt[usecase->out_snd_device] != 0) {
                tfa_98xx_audio_mode = Audio_Mode_Hs_Hfp;
                data->route_cnt[tfa_98xx_audio_mode]++;
                ALOGV("%s: audio_mode hs_hfp\n", __func__);
            }
        } else if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER) {
            if ((mode == AUDIO_MODE_IN_CALL) || audio_extn_hfp_is_active(data->adev)) {
                if (audio_extn_hfp_is_active(data->adev)) {
                    if(data->adev->snd_dev_ref_cnt[usecase->out_snd_device] != 0) {
                        tfa_98xx_audio_mode = Audio_Mode_Hfp_Client;
                        data->route_cnt[tfa_98xx_audio_mode]++;
                        ALOGV("%s: audio_mode hfp client\n", __func__);
                    }
                } else {
                    if(data->adev->snd_dev_ref_cnt[usecase->out_snd_device] != 0) {
                        tfa_98xx_audio_mode = Audio_Mode_Voice;
                        data->route_cnt[tfa_98xx_audio_mode]++;
                        ALOGV("%s: audio_mode voice\n", __func__);
                    }
                }
            } else {
                if (data->adev->snd_dev_ref_cnt[usecase->out_snd_device] != 0) {
                    tfa_98xx_audio_mode = Audio_Mode_Music_Normal;
                    data->route_cnt[tfa_98xx_audio_mode]++;
                    ALOGV("%s: tfa_98xx_audio_mode music\n", __func__);
                }
            }
        } else {
            ALOGE("%s: no device match \n", __func__);
        }
    }
    ALOGV("%s: tfa_98xx_audio_mode %d exit\n", __func__, tfa_98xx_audio_mode);

    return tfa_98xx_audio_mode;
}

static int tfa_98xx_set_func_mode(int enable, struct audio_device *adev, exTfa98xx_func_mode_t func_mode)
{
    struct speaker_data *data = tfa98xx_speaker_data;
    char paths[32] = "init_smart_pa";

    if (data) {
        switch(func_mode) {
            case Func_Mode_Speaker:
                strcat(paths, " func_speaker");
                break;
            case Func_Mode_BT:
                strcat(paths, " func_bt");
                break;
            default:
                ALOGE("%s: function %d not support!\n",__func__, func_mode);
                return -EINVAL;
        }

        ALOGV("%s: mixer paths is: %s, enable: %d\n", __func__, paths, enable);
        adev_i2s_clock_operation(enable, adev, paths);
    }
    return 0;
}

static exTfa98xx_func_mode_t tfa_98xx_get_func_mode(exTfa98xx_audio_mode_t audio_mode)
{
    exTfa98xx_func_mode_t func_mode = Func_Mode_None;

    switch(audio_mode) {
        case Audio_Mode_Music_Normal:
        case Audio_Mode_Voice:
            ALOGV("%s: tfa_98xx_func_mode speaker \n", __func__);
            func_mode = Func_Mode_Speaker;
            break;
        case Audio_Mode_Hfp_Client:
        case Audio_Mode_Hs_Hfp:
            ALOGV("%s: tfa_98xx_func_mode bt \n", __func__);
            func_mode = Func_Mode_BT;
            break;
        default:
            break;
    }
    return func_mode;
}

static void tfa_98xx_disable_speaker(void)
{
    struct speaker_data *data = tfa98xx_speaker_data;
    int ret = 0;

    ret = data->set_speaker_off();
    if (ret) {
        ALOGE("%s: exTfa98xx_speakeroff failed result = %d\n", __func__, ret);
        goto on_error;
    }

    ret = tfa_98xx_set_audio_mode(I2S_CLOCK_DISABLE, data->adev, current_audio_mode);
    if (ret) {
        ALOGE("%s: tfa_98xx_set_audio_mode disable failed return %d\n", __func__, ret);
        goto on_error;
    }
    current_audio_mode = Audio_Mode_None;
on_error:
    return;

}


void audio_extn_tfa_98xx_disable_speaker(snd_device_t snd_device)
{
    struct speaker_data *data = tfa98xx_speaker_data;
    int i = 0;
    exTfa98xx_audio_mode_t new_audio_mode = Audio_Mode_None;

    ALOGV("%s: enter\n", __func__);

    if (data) {
        if ((current_audio_mode == Audio_Mode_None) || (snd_device > SND_DEVICE_OUT_END))
            goto on_exit;

        switch(snd_device) {
            case SND_DEVICE_OUT_SPEAKER:
                new_audio_mode = Audio_Mode_Music_Normal;
                break;
            case SND_DEVICE_OUT_VOICE_SPEAKER:
                new_audio_mode = Audio_Mode_Voice;
                break;
            case SND_DEVICE_OUT_VOICE_SPEAKER_HFP:
                new_audio_mode = Audio_Mode_Hfp_Client;
                break;
            case SND_DEVICE_OUT_BT_SCO:
                new_audio_mode = Audio_Mode_Hs_Hfp;
                break;
            default:
                break;
        }

        if ((new_audio_mode == Audio_Mode_None) || (data->ref_cnt[new_audio_mode] <= 0)) {
            ALOGE("%s: device ref cnt is already 0", __func__);
            goto on_exit;
        }

        data->ref_cnt[new_audio_mode]--;

        for (i = 0; i < Audio_Mode_Max; i++) {
            if (data->ref_cnt[i] > 0) {
                ALOGD("%s: exTfa98xx_speaker still in use\n", __func__);
                goto on_exit;
            }
        }

        tfa_98xx_disable_speaker();
    }

    ALOGV("%s: exit\n", __func__);
on_exit:
    return;
}

int audio_extn_tfa_98xx_enable_speaker(void)
{
    struct speaker_data *data = tfa98xx_speaker_data;
    exTfa98xx_audio_mode_t new_audio_mode = Audio_Mode_Music_Normal;
    int ret = 0;
    int i = 0;

    ALOGV("%s: enter\n", __func__);

    if (data) {

        new_audio_mode = tfa_98xx_get_audio_mode(data);
        if ((new_audio_mode != Audio_Mode_None) && (data->ref_cnt[new_audio_mode] >= 1)) {
            ALOGD("%s, mode %d already active!", __func__, new_audio_mode);
            data->ref_cnt[new_audio_mode]++;
            goto on_exit;
        }

        ret = tfa_98xx_set_audio_mode(I2S_CLOCK_ENABLE, data->adev, new_audio_mode);
        if (ret) {
            ALOGE("%s: tfa_98xx_set_audio_mode enable failed return %d\n", __func__, ret);
            goto on_exit;
        }

        ret = data->set_speaker_on(new_audio_mode);
        if (ret) {
            ALOGE("%s: exTfa98xx_speakeron failed result = %d\n", __func__, ret);
            goto on_exit;
        }

        current_audio_mode = new_audio_mode;
        for (i = 0; i < Audio_Mode_Max; i++) {
            data->ref_cnt[i] = data->route_cnt[i];
        }
        data->update_ref_cnt = false;
    }

    ALOGV("%s: exit\n", __func__);

on_exit:
    return ret;

}

void audio_extn_tfa_98xx_set_mode(void)
{
    int ret = 0;
    struct speaker_data *data = tfa98xx_speaker_data;
    exTfa98xx_audio_mode_t new_audio_mode = Audio_Mode_None;
    exTfa98xx_func_mode_t new_func_mode = Func_Mode_None;

    ALOGV("%s: enter\n", __func__);

    if (data) {
        new_audio_mode = tfa_98xx_get_audio_mode(data);

        new_func_mode = tfa_98xx_get_func_mode(new_audio_mode);
        if (new_func_mode == Func_Mode_None)
            return;

        ret = tfa_98xx_set_func_mode(I2S_CLOCK_ENABLE, data->adev, new_func_mode);
        if (ret)
        {
            ALOGE("%s: tfa_98xx_set_func_mode enable return %d\n", __func__, ret);
        }
        data->update_ref_cnt = true;
    }

    ALOGV("%s: exit\n", __func__);
}

void audio_extn_tfa_98xx_update(void)
{
    struct speaker_data *data = tfa98xx_speaker_data;
    exTfa98xx_audio_mode_t new_audio_mode = Audio_Mode_Music_Normal;

    ALOGD("%s: enter\n", __func__);

    if (data) {

        new_audio_mode = tfa_98xx_get_audio_mode(data);
        if (new_audio_mode <= current_audio_mode) {
            ALOGE("%s: audio_extn_tfa_98xx_update same mode\n", __func__);
            if (data->update_ref_cnt == true) {
                data->ref_cnt[new_audio_mode]++;
                data->update_ref_cnt = false;
            }
            goto on_error;
        }

        if (current_audio_mode != Audio_Mode_None) {
            tfa_98xx_disable_speaker();
        }

        audio_extn_tfa_98xx_enable_speaker();

    }

    ALOGV("%s: exit\n", __func__);
on_error:
    return;

}


void audio_extn_tfa_98xx_set_voice_vol(int vol)
{
    struct speaker_data *data = tfa98xx_speaker_data;

    if (data)
        data->set_speaker_volume_step(vol, vol);
}

bool audio_extn_tfa_98xx_is_supported(void)
{
    struct speaker_data *data = tfa98xx_speaker_data;
    if (data)
        return true;
    else
        return false;
}

int audio_extn_tfa_98xx_init(struct audio_device *adev)
{
    int ret = 0;
    struct speaker_data *data = open_speaker_bundle();

    ALOGV("%s: enter\n", __func__);

    if (data) {
        ret = tfa_98xx_set_audio_mode(I2S_CLOCK_ENABLE, adev, Audio_Mode_Music_Normal);
        if (ret) {
            ALOGE("%s: tfa_98xx_set_audio_mode enable return %d\n", __func__, ret);
            goto err_init;
        }

        ret = data->set_speaker_calibration(0);
        if (ret) {
            ALOGE("%s: exTfa98xx_calibration return %d\n", __func__, ret);
            goto err_init;
        }

        ret = tfa_98xx_set_audio_mode(I2S_CLOCK_DISABLE, adev, Audio_Mode_Music_Normal);
        if (ret) {
            ALOGE("%s: tfa_98xx_set_audio_mode disable return %d\n", __func__, ret);
            goto err_init;
        }

        data->adev = adev;
        tfa98xx_speaker_data = data;
        ALOGV("%s: exit\n", __func__);
        return 0;

    }

err_init:
    close_speaker_bundle(data);
    return -EINVAL;
}

void audio_extn_tfa_98xx_deinit(void)
{
    struct speaker_data *data = tfa98xx_speaker_data;

    if (data) {
        data->set_speaker_off();
        close_speaker_bundle(data);
        tfa98xx_speaker_data = NULL;
    }
}
+40 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading