• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <log/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 
open_speaker_bundle()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 
close_speaker_bundle(struct speaker_data * sd)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 
adev_i2s_clock_operation(int enable,struct audio_device * adev,char * paths)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 
tfa_98xx_set_audio_mode(int enable,struct audio_device * adev,exTfa98xx_audio_mode_t audio_mode)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 
tfa_98xx_get_audio_mode(struct speaker_data * data)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 
tfa_98xx_set_func_mode(int enable,struct audio_device * adev,exTfa98xx_func_mode_t func_mode)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 
tfa_98xx_get_func_mode(exTfa98xx_audio_mode_t audio_mode)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 
tfa_98xx_disable_speaker(void)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 
audio_extn_tfa_98xx_disable_speaker(snd_device_t snd_device)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 
audio_extn_tfa_98xx_enable_speaker(void)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 
audio_extn_tfa_98xx_set_mode(void)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 
audio_extn_tfa_98xx_set_mode_bt(void)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 
audio_extn_tfa_98xx_update(void)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 
audio_extn_tfa_98xx_set_voice_vol(float vol)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 
audio_extn_tfa_98xx_is_supported(void)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 
audio_extn_tfa_98xx_init(struct audio_device * adev)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 
audio_extn_tfa_98xx_deinit(void)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