Home | History | Annotate | Download | only in audio_extn
      1 /*
      2  * Copyright (C) 2013-2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "tfa_98xx"
     18 /*#define LOG_NDEBUG 0*/
     19 #include <cutils/log.h>
     20 
     21 #include <stdlib.h>
     22 #include <audio_hw.h>
     23 #include <dlfcn.h>
     24 #include "audio_extn.h"
     25 #include <platform.h>
     26 #include <math.h>
     27 
     28 #define LIB_SPEAKER_BUNDLE "/system/lib/libexTfa98xx.so"
     29 
     30 
     31 enum exTfa98xx_Audio_Mode
     32 {
     33     Audio_Mode_None = -1,
     34     Audio_Mode_Music_Normal,
     35     Audio_Mode_Hfp_Client,
     36     Audio_Mode_Voice,
     37     Audio_Mode_Hs_Hfp,
     38     Audio_Mode_Max
     39 };
     40 typedef enum exTfa98xx_Audio_Mode exTfa98xx_audio_mode_t;
     41 
     42 enum exTfa98xx_Func_Mode
     43 {
     44     Func_Mode_None = -1,
     45     Func_Mode_Speaker,
     46     Func_Mode_BT
     47 };
     48 typedef enum exTfa98xx_Func_Mode exTfa98xx_func_mode_t;
     49 
     50 #define I2S_CLOCK_ENABLE        1
     51 #define I2S_CLOCK_DISABLE       0
     52 #define HFP_MAX_VOLUME          (15.000000)
     53 #define TFA_98XX_HFP_VSETPS     (5.0)
     54 
     55 exTfa98xx_audio_mode_t current_audio_mode = Audio_Mode_None;
     56 
     57 typedef int (*set_speaker_on_t)(exTfa98xx_audio_mode_t);
     58 typedef int (*set_speaker_off_t)(void);
     59 typedef int (*set_speaker_calibration_t)(int);
     60 typedef void (*set_speaker_volume_step_t)(int, int);
     61 
     62 
     63 struct speaker_data {
     64     struct audio_device *adev;
     65     void *speaker_bundle;
     66     set_speaker_on_t set_speaker_on;
     67     set_speaker_off_t set_speaker_off;
     68     set_speaker_calibration_t set_speaker_calibration;
     69     set_speaker_volume_step_t set_speaker_volume_step;
     70     int ref_cnt[Audio_Mode_Max];
     71     int route_cnt[Audio_Mode_Max];
     72     bool update_ref_cnt;
     73 };
     74 
     75 struct speaker_data *tfa98xx_speaker_data = NULL;
     76 
     77 static struct speaker_data* open_speaker_bundle()
     78 {
     79     struct speaker_data *sd = calloc(1, sizeof(struct speaker_data));
     80 
     81     sd->speaker_bundle = dlopen(LIB_SPEAKER_BUNDLE, RTLD_NOW);
     82     if (sd->speaker_bundle == NULL) {
     83         ALOGE("%s: DLOPEN failed for %s", __func__, LIB_SPEAKER_BUNDLE);
     84         goto error;
     85     } else {
     86         ALOGV("%s: DLOPEN successful for %s", __func__, LIB_SPEAKER_BUNDLE);
     87 
     88         sd->set_speaker_on = (set_speaker_on_t)dlsym(sd->speaker_bundle,
     89                                              "exTfa98xx_speakeron");
     90         if (sd->set_speaker_on == NULL) {
     91             ALOGE("%s: dlsym error %s for exTfa98xx_speakeron", __func__,
     92                   dlerror());
     93             goto error;
     94         }
     95         sd->set_speaker_off = (set_speaker_off_t)dlsym(sd->speaker_bundle,
     96                                              "exTfa98xx_speakeroff");
     97         if (sd->set_speaker_off == NULL) {
     98             ALOGE("%s: dlsym error %s for exTfa98xx_speakeroff", __func__,
     99                   dlerror());
    100             goto error;
    101         }
    102         sd->set_speaker_volume_step = (set_speaker_volume_step_t)dlsym(sd->speaker_bundle,
    103                                              "exTfa98xx_setvolumestep");
    104         if (sd->set_speaker_volume_step == NULL) {
    105             ALOGE("%s: dlsym error %s for exTfa98xx_setvolumestep",
    106                   __func__, dlerror());
    107             goto error;
    108         }
    109         sd->set_speaker_calibration = (set_speaker_calibration_t)dlsym(sd->speaker_bundle,
    110                                              "exTfa98xx_calibration");
    111         if (sd->set_speaker_calibration == NULL) {
    112             ALOGE("%s: dlsym error %s for exTfa98xx_calibration",
    113                   __func__, dlerror());
    114             goto error;
    115         }
    116     }
    117     return sd;
    118 
    119 error:
    120     free(sd);
    121     return 0;
    122 }
    123 
    124 static void close_speaker_bundle(struct speaker_data *sd)
    125 {
    126     if (sd != NULL) {
    127         dlclose(sd->speaker_bundle);
    128         free(sd);
    129         sd = NULL;
    130     }
    131 }
    132 
    133 static int adev_i2s_clock_operation(int enable, struct audio_device *adev, char *paths)
    134 {
    135     int ret = -1;
    136 
    137     ALOGD("%s: mixer paths is: %s, enable: %d\n", __func__, paths, enable);
    138     if(I2S_CLOCK_ENABLE == enable) {
    139         ret = audio_route_apply_and_update_path(adev->audio_route, paths);
    140         if(ret) {
    141             ALOGE("%s: audio_route_apply_and_update_path return %d\n", __func__, ret);
    142             return ret;
    143         }
    144     } else {
    145         ret = audio_route_reset_and_update_path(adev->audio_route, paths);
    146         if(ret) {
    147             ALOGE("%s: audio_route_reset_and_update_path return %d\n", __func__, ret);
    148             return ret;
    149         }
    150     }
    151     return 0;
    152 }
    153 
    154 static int tfa_98xx_set_audio_mode(int enable, struct audio_device *adev, exTfa98xx_audio_mode_t audio_mode)
    155 {
    156     char paths[32] = "init_smart_pa";
    157 
    158     switch(audio_mode) {
    159         case Audio_Mode_Music_Normal:
    160             strcat(paths, " music");
    161             break;
    162         case Audio_Mode_Voice:
    163         case Audio_Mode_Hfp_Client:
    164         case Audio_Mode_Hs_Hfp:
    165             strcat(paths, " voice");
    166             break;
    167         default:
    168             ALOGE("%s: function %d not support!\n",__func__, audio_mode);
    169             return -EINVAL;
    170     }
    171 
    172     ALOGV("%s: mixer paths is: %s, enable: %d\n", __func__, paths, enable);
    173     adev_i2s_clock_operation(enable, adev, paths);
    174     return 0;
    175 
    176 }
    177 
    178 static exTfa98xx_audio_mode_t tfa_98xx_get_audio_mode(struct speaker_data *data)
    179 {
    180     exTfa98xx_audio_mode_t tfa_98xx_audio_mode = Audio_Mode_None;
    181     struct listnode *node;
    182     struct audio_usecase *usecase;
    183     audio_mode_t mode = data->adev->mode;
    184     int i = 0;
    185 
    186     ALOGV("%s: enter\n", __func__);
    187 
    188     for (i = 0; i < Audio_Mode_Max; i++)
    189         data->route_cnt[i] = 0;
    190 
    191     list_for_each(node, &data->adev->usecase_list) {
    192         usecase = node_to_item(node, struct audio_usecase, list);
    193         if (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
    194             if(data->adev->snd_dev_ref_cnt[usecase->out_snd_device] != 0) {
    195                 tfa_98xx_audio_mode = Audio_Mode_Hs_Hfp;
    196                 data->route_cnt[tfa_98xx_audio_mode]++;
    197                 ALOGV("%s: audio_mode hs_hfp\n", __func__);
    198             }
    199         } else if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER) {
    200             if ((mode == AUDIO_MODE_IN_CALL) || audio_extn_hfp_is_active(data->adev)) {
    201                 if (audio_extn_hfp_is_active(data->adev)) {
    202                     if(data->adev->snd_dev_ref_cnt[usecase->out_snd_device] != 0) {
    203                         tfa_98xx_audio_mode = Audio_Mode_Hfp_Client;
    204                         data->route_cnt[tfa_98xx_audio_mode]++;
    205                         ALOGV("%s: audio_mode hfp client\n", __func__);
    206                     }
    207                 } else {
    208                     if(data->adev->snd_dev_ref_cnt[usecase->out_snd_device] != 0) {
    209                         tfa_98xx_audio_mode = Audio_Mode_Voice;
    210                         data->route_cnt[tfa_98xx_audio_mode]++;
    211                         ALOGV("%s: audio_mode voice\n", __func__);
    212                     }
    213                 }
    214             } else {
    215                 if (data->adev->snd_dev_ref_cnt[usecase->out_snd_device] != 0) {
    216                     tfa_98xx_audio_mode = Audio_Mode_Music_Normal;
    217                     data->route_cnt[tfa_98xx_audio_mode]++;
    218                     ALOGV("%s: tfa_98xx_audio_mode music\n", __func__);
    219                 }
    220             }
    221         } else {
    222             ALOGE("%s: no device match \n", __func__);
    223         }
    224     }
    225     ALOGV("%s: tfa_98xx_audio_mode %d exit\n", __func__, tfa_98xx_audio_mode);
    226 
    227     return tfa_98xx_audio_mode;
    228 }
    229 
    230 static int tfa_98xx_set_func_mode(int enable, struct audio_device *adev, exTfa98xx_func_mode_t func_mode)
    231 {
    232     struct speaker_data *data = tfa98xx_speaker_data;
    233     char paths[32] = "init_smart_pa";
    234 
    235     if (data) {
    236         switch(func_mode) {
    237             case Func_Mode_Speaker:
    238                 strcat(paths, " func_speaker");
    239                 break;
    240             case Func_Mode_BT:
    241                 strcat(paths, " func_bt");
    242                 break;
    243             default:
    244                 ALOGE("%s: function %d not support!\n",__func__, func_mode);
    245                 return -EINVAL;
    246         }
    247 
    248         ALOGV("%s: mixer paths is: %s, enable: %d\n", __func__, paths, enable);
    249         adev_i2s_clock_operation(enable, adev, paths);
    250     }
    251     return 0;
    252 }
    253 
    254 static exTfa98xx_func_mode_t tfa_98xx_get_func_mode(exTfa98xx_audio_mode_t audio_mode)
    255 {
    256     exTfa98xx_func_mode_t func_mode = Func_Mode_None;
    257 
    258     switch(audio_mode) {
    259         case Audio_Mode_Music_Normal:
    260         case Audio_Mode_Voice:
    261             ALOGV("%s: tfa_98xx_func_mode speaker \n", __func__);
    262             func_mode = Func_Mode_Speaker;
    263             break;
    264         case Audio_Mode_Hfp_Client:
    265         case Audio_Mode_Hs_Hfp:
    266             ALOGV("%s: tfa_98xx_func_mode bt \n", __func__);
    267             func_mode = Func_Mode_BT;
    268             break;
    269         default:
    270             break;
    271     }
    272     return func_mode;
    273 }
    274 
    275 static void tfa_98xx_disable_speaker(void)
    276 {
    277     struct speaker_data *data = tfa98xx_speaker_data;
    278     int ret = 0;
    279 
    280     ret = data->set_speaker_off();
    281     if (ret) {
    282         ALOGE("%s: exTfa98xx_speakeroff failed result = %d\n", __func__, ret);
    283         goto on_error;
    284     }
    285 
    286     ret = tfa_98xx_set_audio_mode(I2S_CLOCK_DISABLE, data->adev, current_audio_mode);
    287     if (ret) {
    288         ALOGE("%s: tfa_98xx_set_audio_mode disable failed return %d\n", __func__, ret);
    289         goto on_error;
    290     }
    291     current_audio_mode = Audio_Mode_None;
    292 on_error:
    293     return;
    294 
    295 }
    296 
    297 
    298 void audio_extn_tfa_98xx_disable_speaker(snd_device_t snd_device)
    299 {
    300     struct speaker_data *data = tfa98xx_speaker_data;
    301     int i = 0;
    302     exTfa98xx_audio_mode_t new_audio_mode = Audio_Mode_None;
    303 
    304     ALOGV("%s: enter\n", __func__);
    305 
    306     if (data) {
    307         if ((current_audio_mode == Audio_Mode_None) || (snd_device > SND_DEVICE_OUT_END))
    308             goto on_exit;
    309 
    310         switch(snd_device) {
    311             case SND_DEVICE_OUT_SPEAKER:
    312                 new_audio_mode = Audio_Mode_Music_Normal;
    313                 break;
    314             case SND_DEVICE_OUT_VOICE_SPEAKER:
    315                 new_audio_mode = Audio_Mode_Voice;
    316                 break;
    317             case SND_DEVICE_OUT_VOICE_SPEAKER_HFP:
    318                 new_audio_mode = Audio_Mode_Hfp_Client;
    319                 break;
    320             case SND_DEVICE_OUT_BT_SCO:
    321                 new_audio_mode = Audio_Mode_Hs_Hfp;
    322                 break;
    323             default:
    324                 break;
    325         }
    326 
    327         if ((new_audio_mode == Audio_Mode_None) || (data->ref_cnt[new_audio_mode] <= 0)) {
    328             ALOGE("%s: device ref cnt is already 0", __func__);
    329             goto on_exit;
    330         }
    331 
    332         data->ref_cnt[new_audio_mode]--;
    333 
    334         for (i = 0; i < Audio_Mode_Max; i++) {
    335             if (data->ref_cnt[i] > 0) {
    336                 ALOGD("%s: exTfa98xx_speaker still in use\n", __func__);
    337                 goto on_exit;
    338             }
    339         }
    340 
    341         if (data->adev->enable_hfp)
    342             data->set_speaker_volume_step(0, 0);
    343 
    344         tfa_98xx_disable_speaker();
    345     }
    346 
    347     ALOGV("%s: exit\n", __func__);
    348 on_exit:
    349     return;
    350 }
    351 
    352 int audio_extn_tfa_98xx_enable_speaker(void)
    353 {
    354     struct speaker_data *data = tfa98xx_speaker_data;
    355     exTfa98xx_audio_mode_t new_audio_mode = Audio_Mode_Music_Normal;
    356     int ret = 0;
    357     int i = 0;
    358 
    359     ALOGV("%s: enter\n", __func__);
    360 
    361     if (data) {
    362 
    363         new_audio_mode = tfa_98xx_get_audio_mode(data);
    364         if ((new_audio_mode != Audio_Mode_None) && (data->ref_cnt[new_audio_mode] >= 1)) {
    365             ALOGD("%s, mode %d already active!", __func__, new_audio_mode);
    366             data->ref_cnt[new_audio_mode]++;
    367             goto on_exit;
    368         }
    369 
    370         ret = tfa_98xx_set_audio_mode(I2S_CLOCK_ENABLE, data->adev, new_audio_mode);
    371         if (ret) {
    372             ALOGE("%s: tfa_98xx_set_audio_mode enable failed return %d\n", __func__, ret);
    373             goto on_exit;
    374         }
    375 
    376         ret = data->set_speaker_on(new_audio_mode);
    377         if (ret) {
    378             ALOGE("%s: exTfa98xx_speakeron failed result = %d\n", __func__, ret);
    379             goto on_exit;
    380         }
    381 
    382         current_audio_mode = new_audio_mode;
    383         for (i = 0; i < Audio_Mode_Max; i++) {
    384             data->ref_cnt[i] = data->route_cnt[i];
    385         }
    386         data->update_ref_cnt = false;
    387     }
    388 
    389     ALOGV("%s: exit\n", __func__);
    390 
    391 on_exit:
    392     return ret;
    393 
    394 }
    395 
    396 void audio_extn_tfa_98xx_set_mode(void)
    397 {
    398     int ret = 0;
    399     struct speaker_data *data = tfa98xx_speaker_data;
    400     exTfa98xx_audio_mode_t new_audio_mode = Audio_Mode_None;
    401     exTfa98xx_func_mode_t new_func_mode = Func_Mode_None;
    402 
    403     ALOGV("%s: enter\n", __func__);
    404 
    405     if (data) {
    406         new_audio_mode = tfa_98xx_get_audio_mode(data);
    407 
    408         new_func_mode = tfa_98xx_get_func_mode(new_audio_mode);
    409         if (new_func_mode == Func_Mode_None)
    410             return;
    411 
    412         ret = tfa_98xx_set_func_mode(I2S_CLOCK_ENABLE, data->adev, new_func_mode);
    413         if (ret) {
    414             ALOGE("%s: tfa_98xx_set_func_mode enable return %d\n", __func__, ret);
    415         }
    416         data->update_ref_cnt = true;
    417     }
    418 
    419     ALOGV("%s: exit\n", __func__);
    420 }
    421 
    422 void audio_extn_tfa_98xx_set_mode_bt(void)
    423 {
    424     struct speaker_data *data = tfa98xx_speaker_data;
    425     int ret = 0;
    426 
    427     if (data) {
    428         ret = tfa_98xx_set_func_mode(I2S_CLOCK_ENABLE, data->adev, Func_Mode_BT);
    429         if (ret) {
    430             ALOGE("%s: tfa_98xx_set_func_mode enable return %d\n", __func__, ret);
    431         }
    432     }
    433 }
    434 
    435 void audio_extn_tfa_98xx_update(void)
    436 {
    437     struct speaker_data *data = tfa98xx_speaker_data;
    438     exTfa98xx_audio_mode_t new_audio_mode = Audio_Mode_Music_Normal;
    439 
    440     ALOGD("%s: enter\n", __func__);
    441 
    442     if (data) {
    443 
    444         new_audio_mode = tfa_98xx_get_audio_mode(data);
    445         if (new_audio_mode <= current_audio_mode) {
    446             ALOGE("%s: audio_extn_tfa_98xx_update same mode\n", __func__);
    447             if (data->update_ref_cnt == true) {
    448                 data->ref_cnt[new_audio_mode]++;
    449                 data->update_ref_cnt = false;
    450             }
    451             goto on_error;
    452         }
    453 
    454         if (current_audio_mode != Audio_Mode_None) {
    455             tfa_98xx_disable_speaker();
    456         }
    457 
    458         audio_extn_tfa_98xx_enable_speaker();
    459 
    460     }
    461 
    462     ALOGV("%s: exit\n", __func__);
    463 on_error:
    464     return;
    465 
    466 }
    467 
    468 void audio_extn_tfa_98xx_set_voice_vol(float vol)
    469 {
    470     struct speaker_data *data = tfa98xx_speaker_data;
    471     int vsteps = 0;
    472 
    473     if (data) {
    474         if (data->adev->enable_hfp) {
    475             if (vol < 0.0) {
    476                 vol = 0.0;
    477             } else {
    478                 vol = ((vol > HFP_MAX_VOLUME) ? 1.0 : (vol / HFP_MAX_VOLUME));
    479             }
    480             vsteps = (int)floorf((1.0 - vol) * TFA_98XX_HFP_VSETPS);
    481         } else {
    482             return;
    483         }
    484         ALOGD("%s: vsteps %d\n", __func__, vsteps);
    485         data->set_speaker_volume_step(vsteps, vsteps);
    486     }
    487 }
    488 
    489 bool audio_extn_tfa_98xx_is_supported(void)
    490 {
    491     struct speaker_data *data = tfa98xx_speaker_data;
    492     if (data)
    493         return true;
    494     else
    495         return false;
    496 }
    497 
    498 int audio_extn_tfa_98xx_init(struct audio_device *adev)
    499 {
    500     int ret = 0;
    501     struct speaker_data *data = open_speaker_bundle();
    502 
    503     ALOGV("%s: enter\n", __func__);
    504 
    505     if (data) {
    506         ret = tfa_98xx_set_audio_mode(I2S_CLOCK_ENABLE, adev, Audio_Mode_Music_Normal);
    507         if (ret) {
    508             ALOGE("%s: tfa_98xx_set_audio_mode enable return %d\n", __func__, ret);
    509             goto err_init;
    510         }
    511 
    512         ret = data->set_speaker_calibration(0);
    513         if (ret) {
    514             ALOGE("%s: exTfa98xx_calibration return %d\n", __func__, ret);
    515         }
    516 
    517         ret = tfa_98xx_set_audio_mode(I2S_CLOCK_DISABLE, adev, Audio_Mode_Music_Normal);
    518         if (ret) {
    519             ALOGE("%s: tfa_98xx_set_audio_mode disable return %d\n", __func__, ret);
    520             goto err_init;
    521         }
    522 
    523         data->adev = adev;
    524         tfa98xx_speaker_data = data;
    525         ALOGV("%s: exit\n", __func__);
    526         return 0;
    527 
    528     }
    529 
    530 err_init:
    531     close_speaker_bundle(data);
    532     return -EINVAL;
    533 }
    534 
    535 void audio_extn_tfa_98xx_deinit(void)
    536 {
    537     struct speaker_data *data = tfa98xx_speaker_data;
    538 
    539     if (data) {
    540         data->set_speaker_off();
    541         close_speaker_bundle(data);
    542         tfa98xx_speaker_data = NULL;
    543     }
    544 }
    545 
    546