1/*
2 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
3 * Not a contribution.
4 *
5 * Copyright (C) 2013 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20#define LOG_TAG "msm8960_platform"
21/*#define LOG_NDEBUG 0*/
22#define LOG_NDDEBUG 0
23
24#include <stdlib.h>
25#include <dlfcn.h>
26#include <cutils/log.h>
27#include <cutils/properties.h>
28#include <audio_hw.h>
29#include <platform_api.h>
30#include "platform.h"
31
32#define LIB_ACDB_LOADER "libacdbloader.so"
33#define LIB_CSD_CLIENT "libcsd-client.so"
34
35/*
36 * This is the sysfs path for the HDMI audio data block
37 */
38#define AUDIO_DATA_BLOCK_PATH "/sys/class/graphics/fb1/audio_data_block"
39#define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
40
41/*
42 * This file will have a maximum of 38 bytes:
43 *
44 * 4 bytes: number of audio blocks
45 * 4 bytes: total length of Short Audio Descriptor (SAD) blocks
46 * Maximum 10 * 3 bytes: SAD blocks
47 */
48#define MAX_SAD_BLOCKS      10
49#define SAD_BLOCK_SIZE      3
50
51/* EDID format ID for LPCM audio */
52#define EDID_FORMAT_LPCM    1
53
54struct audio_block_header
55{
56    int reserved;
57    int length;
58};
59
60
61typedef void (*acdb_deallocate_t)();
62typedef int  (*acdb_init_t)();
63typedef void (*acdb_send_audio_cal_t)(int, int);
64typedef void (*acdb_send_voice_cal_t)(int, int);
65
66typedef int (*csd_client_init_t)();
67typedef int (*csd_client_deinit_t)();
68typedef int (*csd_disable_device_t)();
69typedef int (*csd_enable_device_t)(int, int, uint32_t);
70typedef int (*csd_volume_t)(int);
71typedef int (*csd_mic_mute_t)(int);
72typedef int (*csd_start_voice_t)();
73typedef int (*csd_stop_voice_t)();
74
75
76struct platform_data {
77    struct audio_device *adev;
78    bool fluence_in_spkr_mode;
79    bool fluence_in_voice_call;
80    bool fluence_in_voice_rec;
81    int  fluence_type;
82    int  dualmic_config;
83    bool ec_ref_enabled;
84
85    /* Audio calibration related functions */
86    void *acdb_handle;
87    acdb_init_t acdb_init;
88    acdb_deallocate_t acdb_deallocate;
89    acdb_send_audio_cal_t acdb_send_audio_cal;
90    acdb_send_voice_cal_t acdb_send_voice_cal;
91
92    /* CSD Client related functions for voice call */
93    void *csd_client;
94    csd_client_init_t csd_client_init;
95    csd_client_deinit_t csd_client_deinit;
96    csd_disable_device_t csd_disable_device;
97    csd_enable_device_t csd_enable_device;
98    csd_volume_t csd_volume;
99    csd_mic_mute_t csd_mic_mute;
100    csd_start_voice_t csd_start_voice;
101    csd_stop_voice_t csd_stop_voice;
102};
103
104static const int pcm_device_table[AUDIO_USECASE_MAX][2] = {
105    [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
106    [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {14, 14},
107    [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
108    [USECASE_AUDIO_RECORD] = {0, 0},
109    [USECASE_AUDIO_RECORD_LOW_LATENCY] = {14, 14},
110    [USECASE_VOICE_CALL] = {12, 12},
111};
112
113/* Array to store sound devices */
114static const char * const device_table[SND_DEVICE_MAX] = {
115    [SND_DEVICE_NONE] = "none",
116    /* Playback sound devices */
117    [SND_DEVICE_OUT_HANDSET] = "handset",
118    [SND_DEVICE_OUT_SPEAKER] = "speaker",
119    [SND_DEVICE_OUT_SPEAKER_REVERSE] = "speaker-reverse",
120    [SND_DEVICE_OUT_HEADPHONES] = "headphones",
121    [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones",
122    [SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker",
123    [SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones",
124    [SND_DEVICE_OUT_HDMI] = "hdmi",
125    [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
126    [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
127    [SND_DEVICE_OUT_BT_SCO_WB] = "bt-sco-headset-wb",
128    [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = "voice-tty-full-headphones",
129    [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = "voice-tty-vco-headphones",
130    [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = "voice-tty-hco-handset",
131    [SND_DEVICE_OUT_USB_HEADSET] = "usb-headphones",
132    [SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET] = "speaker-and-usb-headphones",
133
134    /* Capture sound devices */
135    [SND_DEVICE_IN_HANDSET_MIC] = "handset-mic",
136    [SND_DEVICE_IN_SPEAKER_MIC] = "speaker-mic",
137    [SND_DEVICE_IN_HEADSET_MIC] = "headset-mic",
138    [SND_DEVICE_IN_HANDSET_MIC_AEC] = "handset-mic",
139    [SND_DEVICE_IN_SPEAKER_MIC_AEC] = "voice-speaker-mic",
140    [SND_DEVICE_IN_HEADSET_MIC_AEC] = "headset-mic",
141    [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "voice-speaker-mic",
142    [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "voice-headset-mic",
143    [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic",
144    [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic",
145    [SND_DEVICE_IN_BT_SCO_MIC_WB] = "bt-sco-mic-wb",
146    [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic",
147    [SND_DEVICE_IN_VOICE_DMIC] = "voice-dmic-ef",
148    [SND_DEVICE_IN_VOICE_SPEAKER_DMIC] = "voice-speaker-dmic-ef",
149    [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = "voice-tty-full-headset-mic",
150    [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = "voice-tty-vco-handset-mic",
151    [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = "voice-tty-hco-headset-mic",
152    [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic",
153    [SND_DEVICE_IN_VOICE_REC_DMIC] = "voice-rec-dmic-ef",
154    [SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE] = "voice-rec-dmic-ef-fluence",
155    [SND_DEVICE_IN_USB_HEADSET_MIC] = "usb-headset-mic",
156};
157
158/* ACDB IDs (audio DSP path configuration IDs) for each sound device */
159static const int acdb_device_table[SND_DEVICE_MAX] = {
160    [SND_DEVICE_NONE] = -1,
161    [SND_DEVICE_OUT_HANDSET] = 7,
162    [SND_DEVICE_OUT_SPEAKER] = 14,
163    [SND_DEVICE_OUT_SPEAKER_REVERSE] = 14,
164    [SND_DEVICE_OUT_HEADPHONES] = 10,
165    [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = 10,
166    [SND_DEVICE_OUT_VOICE_SPEAKER] = 14,
167    [SND_DEVICE_OUT_VOICE_HEADPHONES] = 10,
168    [SND_DEVICE_OUT_HDMI] = 18,
169    [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 14,
170    [SND_DEVICE_OUT_BT_SCO] = 22,
171    [SND_DEVICE_OUT_BT_SCO_WB] = 39,
172    [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = 17,
173    [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = 17,
174    [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = 37,
175    [SND_DEVICE_OUT_USB_HEADSET] = 45,
176    [SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET] = 14,
177
178    [SND_DEVICE_IN_HANDSET_MIC] = 4,
179    [SND_DEVICE_IN_SPEAKER_MIC] = 4,
180    [SND_DEVICE_IN_HEADSET_MIC] = 8,
181    [SND_DEVICE_IN_HANDSET_MIC_AEC] = 40,
182    [SND_DEVICE_IN_SPEAKER_MIC_AEC] = 42,
183    [SND_DEVICE_IN_HEADSET_MIC_AEC] = 47,
184    [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = 11,
185    [SND_DEVICE_IN_VOICE_HEADSET_MIC] = 8,
186    [SND_DEVICE_IN_HDMI_MIC] = 4,
187    [SND_DEVICE_IN_BT_SCO_MIC] = 21,
188    [SND_DEVICE_IN_BT_SCO_MIC_WB] = 38,
189    [SND_DEVICE_IN_CAMCORDER_MIC] = 61,
190    [SND_DEVICE_IN_VOICE_DMIC] = 6,
191    [SND_DEVICE_IN_VOICE_SPEAKER_DMIC] = 13,
192    [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = 16,
193    [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = 36,
194    [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = 16,
195    [SND_DEVICE_IN_VOICE_REC_MIC] = 62,
196    [SND_DEVICE_IN_USB_HEADSET_MIC] = 44,
197    /* TODO: Update with proper acdb ids */
198    [SND_DEVICE_IN_VOICE_REC_DMIC] = 62,
199    [SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE] = 6,
200};
201
202#define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL)
203#define LOW_LATENCY_PLATFORM_DELAY (13*1000LL)
204
205void platform_set_echo_reference(void *platform, bool enable)
206{
207    struct platform_data *my_data = (struct platform_data *)platform;
208    struct audio_device *adev = my_data->adev;
209
210    if (enable) {
211        my_data->ec_ref_enabled = enable;
212        audio_route_apply_and_update_path(adev->audio_route, "echo-reference");
213    } else {
214        if (my_data->ec_ref_enabled) {
215            audio_route_reset_and_update_path(adev->audio_route, "echo-reference");
216            my_data->ec_ref_enabled = enable;
217        } else {
218            ALOGV("EC Reference is already disabled: %d", my_data->ec_ref_enabled);
219        }
220    }
221
222    ALOGV("Setting EC Reference: %d", enable);
223}
224
225void *platform_init(struct audio_device *adev)
226{
227    char platform[PROPERTY_VALUE_MAX];
228    char baseband[PROPERTY_VALUE_MAX];
229    char value[PROPERTY_VALUE_MAX];
230    struct platform_data *my_data;
231    const char *snd_card_name;
232
233    adev->mixer = mixer_open(MIXER_CARD);
234
235    if (!adev->mixer) {
236        ALOGE("Unable to open the mixer, aborting.");
237        return NULL;
238    }
239
240    adev->audio_route = audio_route_init(MIXER_CARD, MIXER_XML_PATH);
241    if (!adev->audio_route) {
242        ALOGE("%s: Failed to init audio route controls, aborting.", __func__);
243        mixer_close(adev->mixer);
244        return NULL;
245    }
246
247    my_data = calloc(1, sizeof(struct platform_data));
248
249    snd_card_name = mixer_get_name(adev->mixer);
250
251    my_data->adev = adev;
252    my_data->fluence_in_spkr_mode = false;
253    my_data->fluence_in_voice_call = false;
254    my_data->fluence_in_voice_rec = false;
255    my_data->fluence_type = FLUENCE_NONE;
256
257    property_get("ro.qc.sdk.audio.fluencetype", value, "");
258    if (!strncmp("fluencepro", value, sizeof("fluencepro"))) {
259        my_data->fluence_type = FLUENCE_QUAD_MIC;
260    } else if (!strncmp("fluence", value, sizeof("fluence"))) {
261        my_data->fluence_type = FLUENCE_DUAL_MIC;
262    } else {
263        my_data->fluence_type = FLUENCE_NONE;
264    }
265
266    if (my_data->fluence_type != FLUENCE_NONE) {
267        property_get("persist.audio.fluence.voicecall",value,"");
268        if (!strncmp("true", value, sizeof("true"))) {
269            my_data->fluence_in_voice_call = true;
270        }
271
272        property_get("persist.audio.fluence.voicerec",value,"");
273        if (!strncmp("true", value, sizeof("true"))) {
274            my_data->fluence_in_voice_rec = true;
275        }
276
277        property_get("persist.audio.fluence.speaker",value,"");
278        if (!strncmp("true", value, sizeof("true"))) {
279            my_data->fluence_in_spkr_mode = true;
280        }
281    }
282
283    my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
284    if (my_data->acdb_handle == NULL) {
285        ALOGE("%s: DLOPEN failed for %s", __func__, LIB_ACDB_LOADER);
286    } else {
287        ALOGV("%s: DLOPEN successful for %s", __func__, LIB_ACDB_LOADER);
288        my_data->acdb_deallocate = (acdb_deallocate_t)dlsym(my_data->acdb_handle,
289                                                    "acdb_loader_deallocate_ACDB");
290        my_data->acdb_send_audio_cal = (acdb_send_audio_cal_t)dlsym(my_data->acdb_handle,
291                                                    "acdb_loader_send_audio_cal");
292        if (!my_data->acdb_send_audio_cal)
293            ALOGW("%s: Could not find the symbol acdb_send_audio_cal from %s",
294                  __func__, LIB_ACDB_LOADER);
295        my_data->acdb_send_voice_cal = (acdb_send_voice_cal_t)dlsym(my_data->acdb_handle,
296                                                    "acdb_loader_send_voice_cal");
297        my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
298                                                    "acdb_loader_init_ACDB");
299        if (my_data->acdb_init == NULL)
300            ALOGE("%s: dlsym error %s for acdb_loader_init_ACDB", __func__, dlerror());
301        else
302            my_data->acdb_init();
303    }
304
305    /* If platform is Fusion3, load CSD Client specific symbols
306     * Voice call is handled by MDM and apps processor talks to
307     * MDM through CSD Client
308     */
309    property_get("ro.board.platform", platform, "");
310    property_get("ro.baseband", baseband, "");
311    if (!strcmp("msm8960", platform) && !strcmp("mdm", baseband)) {
312        my_data->csd_client = dlopen(LIB_CSD_CLIENT, RTLD_NOW);
313        if (my_data->csd_client == NULL)
314            ALOGE("%s: DLOPEN failed for %s", __func__, LIB_CSD_CLIENT);
315    }
316
317    if (my_data->csd_client) {
318        ALOGV("%s: DLOPEN successful for %s", __func__, LIB_CSD_CLIENT);
319        my_data->csd_client_deinit = (csd_client_deinit_t)dlsym(my_data->csd_client,
320                                                    "csd_client_deinit");
321        my_data->csd_disable_device = (csd_disable_device_t)dlsym(my_data->csd_client,
322                                                    "csd_client_disable_device");
323        my_data->csd_enable_device = (csd_enable_device_t)dlsym(my_data->csd_client,
324                                                    "csd_client_enable_device");
325        my_data->csd_start_voice = (csd_start_voice_t)dlsym(my_data->csd_client,
326                                                    "csd_client_start_voice");
327        my_data->csd_stop_voice = (csd_stop_voice_t)dlsym(my_data->csd_client,
328                                                    "csd_client_stop_voice");
329        my_data->csd_volume = (csd_volume_t)dlsym(my_data->csd_client,
330                                                    "csd_client_volume");
331        my_data->csd_mic_mute = (csd_mic_mute_t)dlsym(my_data->csd_client,
332                                                    "csd_client_mic_mute");
333        my_data->csd_client_init = (csd_client_init_t)dlsym(my_data->csd_client,
334                                                    "csd_client_init");
335
336        if (my_data->csd_client_init == NULL) {
337            ALOGE("%s: dlsym error %s for csd_client_init", __func__, dlerror());
338        } else {
339            my_data->csd_client_init();
340        }
341    }
342
343    return my_data;
344}
345
346void platform_deinit(void *platform)
347{
348    struct platform_data *my_data = (struct platform_data *)platform;
349
350    free(platform);
351}
352
353const char *platform_get_snd_device_name(snd_device_t snd_device)
354{
355    if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX)
356        return device_table[snd_device];
357    else
358        return "";
359}
360
361int platform_get_snd_device_name_extn(void *platform, snd_device_t snd_device,
362                                      char *device_name)
363{
364    struct platform_data *my_data = (struct platform_data *)platform;
365
366    if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX) {
367        strlcpy(device_name, device_table[snd_device], DEVICE_NAME_MAX_SIZE);
368    } else {
369        strlcpy(device_name, "", DEVICE_NAME_MAX_SIZE);
370        return -EINVAL;
371    }
372
373    return 0;
374}
375
376void platform_add_backend_name(char *mixer_path, snd_device_t snd_device)
377{
378    if (snd_device == SND_DEVICE_IN_BT_SCO_MIC)
379        strlcat(mixer_path, " bt-sco", MIXER_PATH_MAX_LENGTH);
380    else if (snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB)
381        strlcat(mixer_path, " bt-sco-wb", MIXER_PATH_MAX_LENGTH);
382    else if(snd_device == SND_DEVICE_OUT_BT_SCO)
383        strlcat(mixer_path, " bt-sco", MIXER_PATH_MAX_LENGTH);
384    else if(snd_device == SND_DEVICE_OUT_BT_SCO_WB)
385        strlcat(mixer_path, " bt-sco-wb", MIXER_PATH_MAX_LENGTH);
386    else if (snd_device == SND_DEVICE_OUT_HDMI)
387        strlcat(mixer_path, " hdmi", MIXER_PATH_MAX_LENGTH);
388    else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HDMI)
389        strlcat(mixer_path, " speaker-and-hdmi", MIXER_PATH_MAX_LENGTH);
390}
391
392int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type)
393{
394    int device_id;
395    if (device_type == PCM_PLAYBACK)
396        device_id = pcm_device_table[usecase][0];
397    else
398        device_id = pcm_device_table[usecase][1];
399    return device_id;
400}
401
402int platform_get_snd_device_index(char *snd_device_index_name __unused)
403{
404    return -ENODEV;
405}
406
407int platform_set_snd_device_acdb_id(snd_device_t snd_device __unused,
408                                    unsigned int acdb_id __unused)
409{
410    return -ENODEV;
411}
412
413uint32_t platform_get_compress_offload_buffer_size(audio_offload_info_t* info __unused)
414{
415    ALOGE("%s: Not implemented", __func__);
416    return -ENOSYS;
417}
418
419int platform_get_snd_device_acdb_id(snd_device_t snd_device __unused)
420{
421    ALOGE("%s: Not implemented", __func__);
422    return -ENOSYS;
423}
424
425int platform_set_snd_device_bit_width(snd_device_t snd_device, unsigned int bit_width)
426{
427    ALOGE("%s: Not implemented", __func__);
428    return -ENOSYS;
429}
430
431int platform_get_snd_device_bit_width(snd_device_t snd_device)
432{
433    ALOGE("%s: Not implemented", __func__);
434    return -ENOSYS;
435}
436
437int platform_switch_voice_call_enable_device_config(void *platform __unused,
438                                                    snd_device_t out_snd_device __unused,
439                                                    snd_device_t in_snd_device __unused)
440{
441    ALOGE("%s: Not implemented", __func__);
442    return -ENOSYS;
443}
444
445int platform_switch_voice_call_usecase_route_post(void *platform __unused,
446                                                  snd_device_t out_snd_device __unused,
447                                                  snd_device_t in_snd_device __unused)
448{
449    ALOGE("%s: Not implemented", __func__);
450    return -ENOSYS;
451}
452
453int platform_set_incall_recording_session_id(void *platform __unused,
454                                             uint32_t session_id __unused,
455                                             int rec_mode __unused)
456{
457    ALOGE("%s: Not implemented", __func__);
458    return -ENOSYS;
459}
460
461int platform_stop_incall_recording_usecase(void *platform __unused)
462{
463    ALOGE("%s: Not implemented", __func__);
464    return -ENOSYS;
465}
466
467int platform_get_sample_rate(void *platform __unused, uint32_t *rate __unused)
468{
469    ALOGE("%s: Not implemented", __func__);
470    return -ENOSYS;
471}
472
473int platform_get_default_app_type(void *platform __unused)
474{
475    ALOGE("%s: Not implemented", __func__);
476    return -ENOSYS;
477}
478
479int platform_send_audio_calibration(void *platform, struct audio_usecase *usecase,
480                                    int app_type __unused, int sample_rate __unused)
481{
482    struct platform_data *my_data = (struct platform_data *)platform;
483    int acdb_dev_id, acdb_dev_type;
484    struct audio_device *adev = my_data->adev;
485    int snd_device = SND_DEVICE_OUT_SPEAKER;
486
487    if (usecase->type == PCM_PLAYBACK)
488        snd_device = platform_get_output_snd_device(adev->platform,
489                                            usecase->stream.out->devices);
490    else if ((usecase->type == PCM_HFP_CALL) || (usecase->type == PCM_CAPTURE))
491        snd_device = platform_get_input_snd_device(adev->platform,
492                                            adev->primary_output->devices);
493    acdb_dev_id = acdb_device_table[snd_device];
494    if (acdb_dev_id < 0) {
495        ALOGE("%s: Could not find acdb id for device(%d)",
496              __func__, snd_device);
497        return -EINVAL;
498    }
499    if (my_data->acdb_send_audio_cal) {
500        ("%s: sending audio calibration for snd_device(%d) acdb_id(%d)",
501              __func__, snd_device, acdb_dev_id);
502        if (snd_device >= SND_DEVICE_OUT_BEGIN &&
503                snd_device < SND_DEVICE_OUT_END)
504            acdb_dev_type = ACDB_DEV_TYPE_OUT;
505        else
506            acdb_dev_type = ACDB_DEV_TYPE_IN;
507        my_data->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type);
508    }
509    return 0;
510}
511
512int platform_switch_voice_call_device_pre(void *platform)
513{
514    struct platform_data *my_data = (struct platform_data *)platform;
515    int ret = 0;
516
517    if (my_data->csd_client != NULL) {
518        /* This must be called before disabling the mixer controls on APQ side */
519        if (my_data->csd_disable_device == NULL) {
520            ALOGE("%s: dlsym error for csd_disable_device", __func__);
521        } else {
522            ret = my_data->csd_disable_device();
523            if (ret < 0) {
524                ALOGE("%s: csd_client_disable_device, failed, error %d",
525                      __func__, ret);
526            }
527        }
528    }
529    return ret;
530}
531
532int platform_switch_voice_call_device_post(void *platform,
533                                           snd_device_t out_snd_device,
534                                           snd_device_t in_snd_device)
535{
536    struct platform_data *my_data = (struct platform_data *)platform;
537    int acdb_rx_id, acdb_tx_id;
538    int ret = 0;
539
540    if (my_data->csd_client) {
541        if (my_data->csd_enable_device == NULL) {
542            ALOGE("%s: dlsym error for csd_enable_device",
543                  __func__);
544        } else {
545            acdb_rx_id = acdb_device_table[out_snd_device];
546            acdb_tx_id = acdb_device_table[in_snd_device];
547
548            if (acdb_rx_id > 0 || acdb_tx_id > 0) {
549                ret = my_data->csd_enable_device(acdb_rx_id, acdb_tx_id,
550                                                    my_data->adev->acdb_settings);
551                if (ret < 0) {
552                    ALOGE("%s: csd_enable_device, failed, error %d",
553                          __func__, ret);
554                }
555            } else {
556                ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__,
557                      acdb_rx_id, acdb_tx_id);
558            }
559        }
560    }
561
562    return ret;
563}
564
565int platform_start_voice_call(void *platform, uint32_t vsid __unused)
566{
567    struct platform_data *my_data = (struct platform_data *)platform;
568    int ret = 0;
569
570    if (my_data->csd_client) {
571        if (my_data->csd_start_voice == NULL) {
572            ALOGE("dlsym error for csd_client_start_voice");
573            ret = -ENOSYS;
574        } else {
575            ret = my_data->csd_start_voice();
576            if (ret < 0) {
577                ALOGE("%s: csd_start_voice error %d\n", __func__, ret);
578            }
579        }
580    }
581
582    return ret;
583}
584
585int platform_stop_voice_call(void *platform, uint32_t vsid __unused)
586{
587    struct platform_data *my_data = (struct platform_data *)platform;
588    int ret = 0;
589
590    if (my_data->csd_client) {
591        if (my_data->csd_stop_voice == NULL) {
592            ALOGE("dlsym error for csd_stop_voice");
593        } else {
594            ret = my_data->csd_stop_voice();
595            if (ret < 0) {
596                ALOGE("%s: csd_stop_voice error %d\n", __func__, ret);
597            }
598        }
599    }
600
601    return ret;
602}
603
604int platform_set_voice_volume(void *platform, int volume)
605{
606    struct platform_data *my_data = (struct platform_data *)platform;
607    int ret = 0;
608
609    if (my_data->csd_client) {
610        if (my_data->csd_volume == NULL) {
611            ALOGE("%s: dlsym error for csd_volume", __func__);
612        } else {
613            ret = my_data->csd_volume(volume);
614            if (ret < 0) {
615                ALOGE("%s: csd_volume error %d", __func__, ret);
616            }
617        }
618    } else {
619        ALOGE("%s: No CSD Client present", __func__);
620    }
621
622    return ret;
623}
624
625int platform_set_mic_mute(void *platform, bool state)
626{
627    struct platform_data *my_data = (struct platform_data *)platform;
628    int ret = 0;
629
630    if (my_data->adev->mode == AUDIO_MODE_IN_CALL) {
631        if (my_data->csd_client) {
632            if (my_data->csd_mic_mute == NULL) {
633                ALOGE("%s: dlsym error for csd_mic_mute", __func__);
634            } else {
635                ret = my_data->csd_mic_mute(state);
636                if (ret < 0) {
637                    ALOGE("%s: csd_mic_mute error %d", __func__, ret);
638                }
639            }
640        } else {
641            ALOGE("%s: No CSD Client present", __func__);
642        }
643    }
644
645    return ret;
646}
647
648int platform_set_device_mute(void *platform __unused, bool state __unused, char *dir __unused)
649{
650    ALOGE("%s: Not implemented", __func__);
651    return -ENOSYS;
652}
653
654snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices)
655{
656    struct platform_data *my_data = (struct platform_data *)platform;
657    struct audio_device *adev = my_data->adev;
658    audio_mode_t mode = adev->mode;
659    snd_device_t snd_device = SND_DEVICE_NONE;
660
661    ALOGV("%s: enter: output devices(%#x)", __func__, devices);
662    if (devices == AUDIO_DEVICE_NONE ||
663        devices & AUDIO_DEVICE_BIT_IN) {
664        ALOGV("%s: Invalid output devices (%#x)", __func__, devices);
665        goto exit;
666    }
667
668    if (mode == AUDIO_MODE_IN_CALL) {
669        if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
670            devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
671            if (adev->voice.tty_mode == TTY_MODE_FULL)
672                snd_device = SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES;
673            else if (adev->voice.tty_mode == TTY_MODE_VCO)
674                snd_device = SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES;
675            else if (adev->voice.tty_mode == TTY_MODE_HCO)
676                snd_device = SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET;
677            else
678                snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES;
679        } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
680            if (adev->bt_wb_speech_enabled)
681                snd_device = SND_DEVICE_OUT_BT_SCO_WB;
682            else
683                snd_device = SND_DEVICE_OUT_BT_SCO;
684        } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
685            snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
686        } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
687            snd_device = SND_DEVICE_OUT_HANDSET;
688        }
689        if (snd_device != SND_DEVICE_NONE) {
690            goto exit;
691        }
692    }
693
694    if (popcount(devices) == 2) {
695        if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
696                        AUDIO_DEVICE_OUT_SPEAKER)) {
697            snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
698        } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
699                               AUDIO_DEVICE_OUT_SPEAKER)) {
700            snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
701        } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL |
702                               AUDIO_DEVICE_OUT_SPEAKER)) {
703            snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
704        } else {
705            ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
706            goto exit;
707        }
708        if (snd_device != SND_DEVICE_NONE) {
709            goto exit;
710        }
711    }
712
713    if (popcount(devices) != 1) {
714        ALOGE("%s: Invalid output devices(%#x)", __func__, devices);
715        goto exit;
716    }
717
718    if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
719        devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
720        snd_device = SND_DEVICE_OUT_HEADPHONES;
721    } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
722        if (adev->speaker_lr_swap)
723            snd_device = SND_DEVICE_OUT_SPEAKER_REVERSE;
724        else
725            snd_device = SND_DEVICE_OUT_SPEAKER;
726    } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
727        if (adev->bt_wb_speech_enabled)
728            snd_device = SND_DEVICE_OUT_BT_SCO_WB;
729        else
730            snd_device = SND_DEVICE_OUT_BT_SCO;
731    } else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
732        snd_device = SND_DEVICE_OUT_HDMI ;
733    } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
734        snd_device = SND_DEVICE_OUT_HANDSET;
735    } else {
736        ALOGE("%s: Unknown device(s) %#x", __func__, devices);
737    }
738exit:
739    ALOGV("%s: exit: snd_device(%s)", __func__, device_table[snd_device]);
740    return snd_device;
741}
742
743snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device)
744{
745    struct platform_data *my_data = (struct platform_data *)platform;
746    struct audio_device *adev = my_data->adev;
747    audio_source_t  source = (adev->active_input == NULL) ?
748                                AUDIO_SOURCE_DEFAULT : adev->active_input->source;
749
750    audio_mode_t    mode   = adev->mode;
751    audio_devices_t in_device = ((adev->active_input == NULL) ?
752                                    AUDIO_DEVICE_NONE : adev->active_input->device)
753                                & ~AUDIO_DEVICE_BIT_IN;
754    audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
755                                AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
756    snd_device_t snd_device = SND_DEVICE_NONE;
757
758    ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
759          __func__, out_device, in_device);
760    if (mode == AUDIO_MODE_IN_CALL) {
761        if (out_device == AUDIO_DEVICE_NONE) {
762            ALOGE("%s: No output device set for voice call", __func__);
763            goto exit;
764        }
765        if (adev->voice.tty_mode != TTY_MODE_OFF) {
766            if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
767                out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
768                switch (adev->voice.tty_mode) {
769                case TTY_MODE_FULL:
770                    snd_device = SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC;
771                    break;
772                case TTY_MODE_VCO:
773                    snd_device = SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC;
774                    break;
775                case TTY_MODE_HCO:
776                    snd_device = SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC;
777                    break;
778                default:
779                    ALOGE("%s: Invalid TTY mode (%#x)", __func__, adev->voice.tty_mode);
780                }
781                goto exit;
782            }
783        }
784        if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
785            out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
786            if (my_data->fluence_type == FLUENCE_NONE ||
787                my_data->fluence_in_voice_call == false) {
788                snd_device = SND_DEVICE_IN_HANDSET_MIC;
789            } else {
790                snd_device = SND_DEVICE_IN_VOICE_DMIC;
791                adev->acdb_settings |= DMIC_FLAG;
792            }
793        } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
794            snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
795        } else if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
796            if (adev->bt_wb_speech_enabled)
797                snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
798            else
799                snd_device = SND_DEVICE_IN_BT_SCO_MIC;
800        } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
801            if (my_data->fluence_type != FLUENCE_NONE &&
802                my_data->fluence_in_voice_call &&
803                my_data->fluence_in_spkr_mode) {
804                if(my_data->fluence_type == FLUENCE_DUAL_MIC) {
805                    adev->acdb_settings |= DMIC_FLAG;
806                    snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC;
807                } else {
808                    adev->acdb_settings |= QMIC_FLAG;
809                    snd_device = SND_DEVICE_IN_VOICE_SPEAKER_QMIC;
810                }
811            } else {
812                snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
813            }
814        }
815    } else if (source == AUDIO_SOURCE_CAMCORDER) {
816        if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
817            in_device & AUDIO_DEVICE_IN_BACK_MIC) {
818            snd_device = SND_DEVICE_IN_CAMCORDER_MIC;
819        }
820    } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) {
821        if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
822            if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
823                snd_device = SND_DEVICE_IN_VOICE_REC_DMIC;
824            else if (my_data->fluence_in_voice_rec)
825                snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE;
826
827            if (snd_device == SND_DEVICE_NONE)
828                snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
829            else
830                adev->acdb_settings |= DMIC_FLAG;
831        }
832    } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
833        if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
834            in_device = AUDIO_DEVICE_IN_BACK_MIC;
835        if (adev->active_input) {
836            if (adev->active_input->enable_aec) {
837                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
838                    snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
839                } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
840                    snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
841                } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
842                    snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
843                }
844                platform_set_echo_reference(adev->platform, true);
845            } else
846                platform_set_echo_reference(adev->platform, false);
847        }
848    } else if (source == AUDIO_SOURCE_DEFAULT) {
849        goto exit;
850    }
851
852
853    if (snd_device != SND_DEVICE_NONE) {
854        goto exit;
855    }
856
857    if (in_device != AUDIO_DEVICE_NONE &&
858            !(in_device & AUDIO_DEVICE_IN_VOICE_CALL) &&
859            !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) {
860        if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
861            snd_device = SND_DEVICE_IN_HANDSET_MIC;
862        } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
863            snd_device = SND_DEVICE_IN_SPEAKER_MIC;
864        } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
865            snd_device = SND_DEVICE_IN_HEADSET_MIC;
866        } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
867            if (adev->bt_wb_speech_enabled)
868                snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
869            else
870                snd_device = SND_DEVICE_IN_BT_SCO_MIC;
871        } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) {
872            snd_device = SND_DEVICE_IN_HDMI_MIC;
873        } else {
874            ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
875            ALOGW("%s: Using default handset-mic", __func__);
876            snd_device = SND_DEVICE_IN_HANDSET_MIC;
877        }
878    } else {
879        if (out_device & AUDIO_DEVICE_OUT_EARPIECE) {
880            snd_device = SND_DEVICE_IN_HANDSET_MIC;
881        } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
882            snd_device = SND_DEVICE_IN_HEADSET_MIC;
883        } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
884            snd_device = SND_DEVICE_IN_SPEAKER_MIC;
885        } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
886            snd_device = SND_DEVICE_IN_HANDSET_MIC;
887        } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
888            if (adev->bt_wb_speech_enabled)
889                snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
890            else
891                snd_device = SND_DEVICE_IN_BT_SCO_MIC;
892        } else if (out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
893            snd_device = SND_DEVICE_IN_HDMI_MIC;
894        } else {
895            ALOGE("%s: Unknown output device(s) %#x", __func__, out_device);
896            ALOGW("%s: Using default handset-mic", __func__);
897            snd_device = SND_DEVICE_IN_HANDSET_MIC;
898        }
899    }
900exit:
901    ALOGV("%s: exit: in_snd_device(%s)", __func__, device_table[snd_device]);
902    return snd_device;
903}
904
905int platform_set_hdmi_channels(void *platform,  int channel_count)
906{
907    struct platform_data *my_data = (struct platform_data *)platform;
908    struct audio_device *adev = my_data->adev;
909    struct mixer_ctl *ctl;
910    const char *channel_cnt_str = NULL;
911    const char *mixer_ctl_name = "HDMI_RX Channels";
912    switch (channel_count) {
913    case 8:
914        channel_cnt_str = "Eight"; break;
915    case 7:
916        channel_cnt_str = "Seven"; break;
917    case 6:
918        channel_cnt_str = "Six"; break;
919    case 5:
920        channel_cnt_str = "Five"; break;
921    case 4:
922        channel_cnt_str = "Four"; break;
923    case 3:
924        channel_cnt_str = "Three"; break;
925    default:
926        channel_cnt_str = "Two"; break;
927    }
928    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
929    if (!ctl) {
930        ALOGE("%s: Could not get ctl for mixer cmd - %s",
931              __func__, mixer_ctl_name);
932        return -EINVAL;
933    }
934    ALOGV("HDMI channel count: %s", channel_cnt_str);
935    mixer_ctl_set_enum_by_string(ctl, channel_cnt_str);
936    return 0;
937}
938
939int platform_edid_get_max_channels(void *platform __unused)
940{
941    FILE *file;
942    struct audio_block_header header;
943    char block[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE];
944    char *sad = block;
945    int num_audio_blocks;
946    int channel_count;
947    int max_channels = 0;
948    int i;
949
950    file = fopen(AUDIO_DATA_BLOCK_PATH, "rb");
951    if (file == NULL) {
952        ALOGE("Unable to open '%s'", AUDIO_DATA_BLOCK_PATH);
953        return 0;
954    }
955
956    /* Read audio block header */
957    fread(&header, 1, sizeof(header), file);
958
959    /* Read SAD blocks, clamping the maximum size for safety */
960    if (header.length > (int)sizeof(block))
961        header.length = (int)sizeof(block);
962    fread(&block, header.length, 1, file);
963
964    fclose(file);
965
966    /* Calculate the number of SAD blocks */
967    num_audio_blocks = header.length / SAD_BLOCK_SIZE;
968
969    for (i = 0; i < num_audio_blocks; i++) {
970        /* Only consider LPCM blocks */
971        if ((sad[0] >> 3) != EDID_FORMAT_LPCM)
972            continue;
973
974        channel_count = (sad[0] & 0x7) + 1;
975        if (channel_count > max_channels)
976            max_channels = channel_count;
977
978        /* Advance to next block */
979        sad += 3;
980    }
981
982    return max_channels;
983}
984
985void platform_get_parameters(void *platform __unused,
986                             struct str_parms *query __unused,
987                             struct str_parms *reply __unused)
988{
989    ALOGE("%s: Not implemented", __func__);
990}
991
992int platform_set_parameters(void *platform __unused, struct str_parms *parms __unused)
993{
994    ALOGE("%s: Not implemented", __func__);
995    return -ENOSYS;
996}
997
998int platform_set_incall_recoding_session_id(void *platform __unused,
999                                            uint32_t session_id __unused)
1000{
1001    ALOGE("%s: Not implemented", __func__);
1002    return -ENOSYS;
1003}
1004
1005int platform_update_lch(void *platform __unused,
1006                        struct voice_session *session __unused,
1007                        enum voice_lch_mode lch_mode __unused)
1008{
1009    ALOGE("%s: Not implemented", __func__);
1010    return -ENOSYS;
1011}
1012
1013int platform_start_incall_music_usecase(void *platform __unused)
1014{
1015    ALOGE("%s: Not implemented", __func__);
1016    return -ENOSYS;
1017}
1018
1019int platform_stop_incall_music_usecase(void *platform __unused)
1020{
1021    ALOGE("%s: Not implemented", __func__);
1022    return -ENOSYS;
1023}
1024
1025/* Delay in Us */
1026int64_t platform_render_latency(audio_usecase_t usecase)
1027{
1028    switch (usecase) {
1029        case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER:
1030            return DEEP_BUFFER_PLATFORM_DELAY;
1031        case USECASE_AUDIO_PLAYBACK_LOW_LATENCY:
1032            return LOW_LATENCY_PLATFORM_DELAY;
1033        default:
1034            return 0;
1035    }
1036}
1037
1038int platform_update_usecase_from_source(int source, int usecase)
1039{
1040    ALOGV("%s: input source :%d", __func__, source);
1041    return usecase;
1042}
1043
1044bool platform_listen_device_needs_event(snd_device_t snd_device __unused)
1045{
1046    return false;
1047}
1048
1049bool platform_listen_usecase_needs_event(audio_usecase_t uc_id __unused)
1050{
1051    return false;
1052}
1053
1054bool platform_check_and_set_codec_backend_cfg(struct audio_device* adev __unused,
1055                                              struct audio_usecase *usecase __unused)
1056{
1057    return false;
1058}
1059
1060int platform_get_usecase_index(const char * usecase __unused)
1061{
1062    return -ENOSYS;
1063}
1064
1065int platform_set_usecase_pcm_id(audio_usecase_t usecase __unused, int32_t type __unused,
1066                                int32_t pcm_id __unused)
1067{
1068    return -ENOSYS;
1069}
1070
1071int platform_set_snd_device_backend(snd_device_t snd_device __unused,
1072                                    const char * backend __unused)
1073{
1074    return -ENOSYS;
1075}
1076
1077bool platform_sound_trigger_device_needs_event(snd_device_t snd_device __unused)
1078{
1079    return false;
1080}
1081
1082bool platform_sound_trigger_usecase_needs_event(audio_usecase_t uc_id  __unused)
1083{
1084    return false;
1085}
1086
1087int platform_set_fluence_type(void *platform __unused, char *value __unused)
1088{
1089    return -ENOSYS;
1090}
1091
1092int platform_get_fluence_type(void *platform __unused, char *value __unused,
1093                              uint32_t len __unused)
1094{
1095    return -ENOSYS;
1096}
1097
1098uint32_t platform_get_pcm_offload_buffer_size(audio_offload_info_t* info __unused)
1099{
1100    return 0;
1101}
1102
1103int platform_set_audio_device_interface(const char * device_name __unused,
1104                                        const char *intf_name __unused,
1105                                        const char *codec_type __unused)
1106{
1107    return -ENOSYS;
1108}
1109