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
31enum 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};
40typedef enum exTfa98xx_Audio_Mode exTfa98xx_audio_mode_t;
41
42enum exTfa98xx_Func_Mode
43{
44    Func_Mode_None = -1,
45    Func_Mode_Speaker,
46    Func_Mode_BT
47};
48typedef 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
55exTfa98xx_audio_mode_t current_audio_mode = Audio_Mode_None;
56
57typedef int (*set_speaker_on_t)(exTfa98xx_audio_mode_t);
58typedef int (*set_speaker_off_t)(void);
59typedef int (*set_speaker_calibration_t)(int);
60typedef void (*set_speaker_volume_step_t)(int, int);
61
62
63struct 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
75struct speaker_data *tfa98xx_speaker_data = NULL;
76
77static 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
119error:
120    free(sd);
121    return 0;
122}
123
124static 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
133static 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
154static 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
178static 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
230static 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
254static 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
275static 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;
292on_error:
293    return;
294
295}
296
297
298void 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__);
348on_exit:
349    return;
350}
351
352int 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
391on_exit:
392    return ret;
393
394}
395
396void 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
422void 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
435void 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__);
463on_error:
464    return;
465
466}
467
468void 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
489bool 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
498int 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
530err_init:
531    close_speaker_bundle(data);
532    return -EINVAL;
533}
534
535void 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