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