platform.c revision 9d0d3f1537b5d157a2c31e0744303524b846446e
1/*
2 * Copyright (C) 2013-2014 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 "msm8974_platform"
18/*#define LOG_NDEBUG 0*/
19#define LOG_NDDEBUG 0
20
21#include <stdlib.h>
22#include <dlfcn.h>
23#include <cutils/log.h>
24#include <cutils/str_parms.h>
25#include <cutils/properties.h>
26#include <audio_hw.h>
27#include <platform_api.h>
28#include "platform.h"
29#ifdef PLATFORM_MSM8084
30#include "mdm_detect.h"
31#endif
32
33#define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
34#define LIB_ACDB_LOADER "libacdbloader.so"
35#define AUDIO_DATA_BLOCK_MIXER_CTL "HDMI EDID"
36
37#define DUALMIC_CONFIG_NONE 0      /* Target does not contain 2 mics */
38#define DUALMIC_CONFIG_ENDFIRE 1
39#define DUALMIC_CONFIG_BROADSIDE 2
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
54/* Retry for delay in FW loading*/
55#define RETRY_NUMBER 10
56#define RETRY_US 500000
57#define MAX_SND_CARD 8
58
59struct audio_block_header
60{
61    int reserved;
62    int length;
63};
64
65/* Audio calibration related functions */
66typedef void (*acdb_deallocate_t)();
67#ifdef PLATFORM_MSM8084
68typedef int  (*acdb_init_t)(char *);
69#else
70typedef int  (*acdb_init_t)();
71#endif
72typedef void (*acdb_send_audio_cal_t)(int, int);
73typedef void (*acdb_send_voice_cal_t)(int, int);
74typedef int (*acdb_reload_vocvoltable_t)(int);
75
76/* Audio calibration related functions */
77struct platform_data {
78    struct audio_device *adev;
79    bool fluence_in_spkr_mode;
80    bool fluence_in_voice_call;
81    bool fluence_in_voice_rec;
82    int  dualmic_config;
83    void *acdb_handle;
84    acdb_init_t acdb_init;
85    acdb_deallocate_t acdb_deallocate;
86    acdb_send_audio_cal_t acdb_send_audio_cal;
87    acdb_send_voice_cal_t acdb_send_voice_cal;
88    acdb_reload_vocvoltable_t  acdb_reload_vocvoltable;
89    struct csd_data *csd;
90    bool ext_speaker;
91    bool ext_earpiece;
92};
93
94static int pcm_device_table[AUDIO_USECASE_MAX][2] = {
95    [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {DEEP_BUFFER_PCM_DEVICE,
96                                            DEEP_BUFFER_PCM_DEVICE},
97    [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
98                                            LOWLATENCY_PCM_DEVICE},
99    [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {MULTIMEDIA2_PCM_DEVICE,
100                                         MULTIMEDIA2_PCM_DEVICE},
101    [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {PLAYBACK_OFFLOAD_DEVICE,
102                                        PLAYBACK_OFFLOAD_DEVICE},
103    [USECASE_AUDIO_RECORD] = {AUDIO_RECORD_PCM_DEVICE,
104                              AUDIO_RECORD_PCM_DEVICE},
105    [USECASE_AUDIO_RECORD_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
106                                          LOWLATENCY_PCM_DEVICE},
107    [USECASE_VOICE_CALL] = {VOICE_CALL_PCM_DEVICE,
108                            VOICE_CALL_PCM_DEVICE},
109    [USECASE_VOICE2_CALL] = {VOICE2_CALL_PCM_DEVICE, VOICE2_CALL_PCM_DEVICE},
110    [USECASE_VOLTE_CALL] = {VOLTE_CALL_PCM_DEVICE, VOLTE_CALL_PCM_DEVICE},
111    [USECASE_QCHAT_CALL] = {QCHAT_CALL_PCM_DEVICE, QCHAT_CALL_PCM_DEVICE},
112    [USECASE_VOWLAN_CALL] = {VOWLAN_CALL_PCM_DEVICE, VOWLAN_CALL_PCM_DEVICE},
113    [USECASE_INCALL_REC_UPLINK] = {AUDIO_RECORD_PCM_DEVICE,
114                                   AUDIO_RECORD_PCM_DEVICE},
115    [USECASE_INCALL_REC_DOWNLINK] = {AUDIO_RECORD_PCM_DEVICE,
116                                     AUDIO_RECORD_PCM_DEVICE},
117    [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = {AUDIO_RECORD_PCM_DEVICE,
118                                                AUDIO_RECORD_PCM_DEVICE},
119    [USECASE_AUDIO_HFP_SCO] = {HFP_PCM_RX, HFP_SCO_RX},
120};
121
122/* Array to store sound devices */
123static const char * const device_table[SND_DEVICE_MAX] = {
124    [SND_DEVICE_NONE] = "none",
125    /* Playback sound devices */
126    [SND_DEVICE_OUT_HANDSET] = "handset",
127    [SND_DEVICE_OUT_SPEAKER] = "speaker",
128    [SND_DEVICE_OUT_SPEAKER_REVERSE] = "speaker-reverse",
129    [SND_DEVICE_OUT_HEADPHONES] = "headphones",
130    [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones",
131    [SND_DEVICE_OUT_VOICE_HANDSET] = "voice-handset",
132    [SND_DEVICE_OUT_VOICE_HAC_HANDSET] = "voice-hac-handset",
133    [SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker",
134    [SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones",
135    [SND_DEVICE_OUT_HDMI] = "hdmi",
136    [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
137    [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
138    [SND_DEVICE_OUT_BT_SCO_WB] = "bt-sco-headset-wb",
139    [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = "voice-handset-tmus",
140    [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = "voice-tty-full-headphones",
141    [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = "voice-tty-vco-headphones",
142    [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = "voice-tty-hco-handset",
143
144    /* Capture sound devices */
145    [SND_DEVICE_IN_HANDSET_MIC] = "handset-mic",
146    [SND_DEVICE_IN_SPEAKER_MIC] = "speaker-mic",
147    [SND_DEVICE_IN_HEADSET_MIC] = "headset-mic",
148    [SND_DEVICE_IN_HANDSET_MIC_AEC] = "handset-mic",
149    [SND_DEVICE_IN_SPEAKER_MIC_AEC] = "speaker-mic-aec",
150    [SND_DEVICE_IN_HEADSET_MIC_AEC] = "headset-mic",
151    [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "voice-speaker-mic",
152    [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "voice-headset-mic",
153    [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic",
154    [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic",
155    [SND_DEVICE_IN_BT_SCO_MIC_WB] = "bt-sco-mic-wb",
156    [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic",
157    [SND_DEVICE_IN_VOICE_DMIC_EF] = "voice-dmic-ef",
158    [SND_DEVICE_IN_VOICE_DMIC_BS] = "voice-dmic-bs",
159    [SND_DEVICE_IN_VOICE_DMIC_EF_TMUS] = "voice-dmic-ef-tmus",
160    [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF] = "voice-speaker-dmic-ef",
161    [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS] = "voice-speaker-dmic-bs",
162    [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = "voice-tty-full-headset-mic",
163    [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = "voice-tty-vco-handset-mic",
164    [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = "voice-tty-hco-headset-mic",
165    [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic",
166    [SND_DEVICE_IN_VOICE_REC_DMIC_EF] = "voice-rec-dmic-ef",
167    [SND_DEVICE_IN_VOICE_REC_DMIC_BS] = "voice-rec-dmic-bs",
168    [SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE] = "voice-rec-dmic-ef-fluence",
169    [SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE] = "voice-rec-dmic-bs-fluence",
170};
171
172/* ACDB IDs (audio DSP path configuration IDs) for each sound device */
173static int acdb_device_table[SND_DEVICE_MAX] = {
174    [SND_DEVICE_NONE] = -1,
175    [SND_DEVICE_OUT_HANDSET] = 7,
176    [SND_DEVICE_OUT_SPEAKER] = 15,
177    [SND_DEVICE_OUT_SPEAKER_REVERSE] = 15,
178    [SND_DEVICE_OUT_HEADPHONES] = 10,
179    [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = 10,
180#ifdef PLATFORM_MSM8084
181    [SND_DEVICE_OUT_VOICE_HANDSET] = 67,
182    [SND_DEVICE_OUT_VOICE_SPEAKER] = 66,
183#else
184    [SND_DEVICE_OUT_VOICE_HANDSET] = 7,
185    [SND_DEVICE_OUT_VOICE_SPEAKER] = 15,
186#endif
187    [SND_DEVICE_OUT_VOICE_HAC_HANDSET] = 53,
188    [SND_DEVICE_OUT_VOICE_HEADPHONES] = 10,
189    [SND_DEVICE_OUT_HDMI] = 18,
190    [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 15,
191    [SND_DEVICE_OUT_BT_SCO] = 22,
192    [SND_DEVICE_OUT_BT_SCO_WB] = 39,
193    [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = ACDB_ID_VOICE_HANDSET_TMUS,
194    [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = 17,
195    [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = 17,
196    [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = 37,
197
198    [SND_DEVICE_IN_HANDSET_MIC] = 4,
199    [SND_DEVICE_IN_SPEAKER_MIC] = 4, /* ToDo: Check if this needs to changed to 11 */
200    [SND_DEVICE_IN_HEADSET_MIC] = 8,
201    [SND_DEVICE_IN_HANDSET_MIC_AEC] = 40,
202    [SND_DEVICE_IN_SPEAKER_MIC_AEC] = 42,
203    [SND_DEVICE_IN_HEADSET_MIC_AEC] = 47,
204    [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = 11,
205    [SND_DEVICE_IN_VOICE_HEADSET_MIC] = 8,
206    [SND_DEVICE_IN_HDMI_MIC] = 4,
207    [SND_DEVICE_IN_BT_SCO_MIC] = 21,
208    [SND_DEVICE_IN_BT_SCO_MIC_WB] = 38,
209    [SND_DEVICE_IN_CAMCORDER_MIC] = 61,
210    [SND_DEVICE_IN_VOICE_DMIC_EF] = 41,
211    [SND_DEVICE_IN_VOICE_DMIC_BS] = 5,
212    [SND_DEVICE_IN_VOICE_DMIC_EF_TMUS] = ACDB_ID_VOICE_DMIC_EF_TMUS,
213    [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF] = 43,
214    [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS] = 12,
215    [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = 16,
216    [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = 36,
217    [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = 16,
218    [SND_DEVICE_IN_VOICE_REC_MIC] = 62,
219    /* TODO: Update with proper acdb ids */
220    [SND_DEVICE_IN_VOICE_REC_DMIC_EF] = 62,
221    [SND_DEVICE_IN_VOICE_REC_DMIC_BS] = 62,
222    [SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE] = 6,
223    [SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE] = 5,
224};
225
226struct name_to_index {
227    char name[100];
228    unsigned int index;
229};
230
231#define TO_NAME_INDEX(X)   #X, X
232
233/* Used to get index from parsed string */
234static const struct name_to_index snd_device_name_index[SND_DEVICE_MAX] = {
235    /* out */
236    {TO_NAME_INDEX(SND_DEVICE_OUT_HANDSET)},
237    {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER)},
238    {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_REVERSE)},
239    {TO_NAME_INDEX(SND_DEVICE_OUT_HEADPHONES)},
240    {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES)},
241    {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HANDSET)},
242    {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER)},
243    {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HEADPHONES)},
244    {TO_NAME_INDEX(SND_DEVICE_OUT_HDMI)},
245    {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_HDMI)},
246    {TO_NAME_INDEX(SND_DEVICE_OUT_BT_SCO)},
247    {TO_NAME_INDEX(SND_DEVICE_OUT_BT_SCO_WB)},
248    {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HANDSET_TMUS)},
249    {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HAC_HANDSET)},
250    {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES)},
251    {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES)},
252    {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET)},
253
254    /* in */
255    {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC)},
256    {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_MIC)},
257    {TO_NAME_INDEX(SND_DEVICE_IN_HEADSET_MIC)},
258    {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC_AEC)},
259    {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_MIC_AEC)},
260    {TO_NAME_INDEX(SND_DEVICE_IN_HEADSET_MIC_AEC)},
261    {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_SPEAKER_MIC)},
262    {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_HEADSET_MIC)},
263    {TO_NAME_INDEX(SND_DEVICE_IN_HDMI_MIC)},
264    {TO_NAME_INDEX(SND_DEVICE_IN_BT_SCO_MIC)},
265    {TO_NAME_INDEX(SND_DEVICE_IN_BT_SCO_MIC_WB)},
266    {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_MIC)},
267    {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_DMIC_EF)},
268    {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_DMIC_BS)},
269    {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_DMIC_EF_TMUS)},
270    {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF)},
271    {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS)},
272    {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC)},
273    {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC)},
274    {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC)},
275    {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_REC_MIC)},
276    {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_REC_DMIC_EF)},
277    {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_REC_DMIC_BS)},
278    {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE)},
279    {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE)},
280};
281
282static char * backend_table[SND_DEVICE_MAX] = {0};
283
284static const struct name_to_index usecase_name_index[AUDIO_USECASE_MAX] = {
285    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_DEEP_BUFFER)},
286    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_LOW_LATENCY)},
287    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_MULTI_CH)},
288    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD)},
289    {TO_NAME_INDEX(USECASE_AUDIO_RECORD)},
290    {TO_NAME_INDEX(USECASE_AUDIO_RECORD_LOW_LATENCY)},
291    {TO_NAME_INDEX(USECASE_VOICE_CALL)},
292    {TO_NAME_INDEX(USECASE_VOICE2_CALL)},
293    {TO_NAME_INDEX(USECASE_VOLTE_CALL)},
294    {TO_NAME_INDEX(USECASE_QCHAT_CALL)},
295    {TO_NAME_INDEX(USECASE_VOWLAN_CALL)},
296    {TO_NAME_INDEX(USECASE_INCALL_REC_UPLINK)},
297    {TO_NAME_INDEX(USECASE_INCALL_REC_DOWNLINK)},
298    {TO_NAME_INDEX(USECASE_INCALL_REC_UPLINK_AND_DOWNLINK)},
299    {TO_NAME_INDEX(USECASE_AUDIO_HFP_SCO)},
300};
301
302#define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL)
303#define LOW_LATENCY_PLATFORM_DELAY (13*1000LL)
304
305static pthread_once_t check_op_once_ctl = PTHREAD_ONCE_INIT;
306static bool is_tmus = false;
307
308static void check_operator()
309{
310    char value[PROPERTY_VALUE_MAX];
311    int mccmnc;
312    property_get("gsm.sim.operator.numeric",value,"0");
313    mccmnc = atoi(value);
314    ALOGD("%s: tmus mccmnc %d", __func__, mccmnc);
315    switch(mccmnc) {
316    /* TMUS MCC(310), MNC(490, 260, 026) */
317    case 310490:
318    case 310260:
319    case 310026:
320    /* Add new TMUS MNC(800, 660, 580, 310, 270, 250, 240, 230, 220, 210, 200, 160) */
321    case 310800:
322    case 310660:
323    case 310580:
324    case 310310:
325    case 310270:
326    case 310250:
327    case 310240:
328    case 310230:
329    case 310220:
330    case 310210:
331    case 310200:
332    case 310160:
333        is_tmus = true;
334        break;
335    }
336}
337
338bool is_operator_tmus()
339{
340    pthread_once(&check_op_once_ctl, check_operator);
341    return is_tmus;
342}
343
344static int set_echo_reference(struct mixer *mixer, const char* ec_ref)
345{
346    struct mixer_ctl *ctl;
347    const char *mixer_ctl_name = "EC_REF_RX";
348
349    ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
350    if (!ctl) {
351        ALOGE("%s: Could not get ctl for mixer cmd - %s",
352              __func__, mixer_ctl_name);
353        return -EINVAL;
354    }
355    ALOGV("Setting EC Reference: %s", ec_ref);
356    mixer_ctl_set_enum_by_string(ctl, ec_ref);
357    return 0;
358}
359
360static struct csd_data *open_csd_client(bool i2s_ext_modem)
361{
362    struct csd_data *csd = calloc(1, sizeof(struct csd_data));
363
364    csd->csd_client = dlopen(LIB_CSD_CLIENT, RTLD_NOW);
365    if (csd->csd_client == NULL) {
366        ALOGE("%s: DLOPEN failed for %s", __func__, LIB_CSD_CLIENT);
367        goto error;
368    } else {
369        ALOGV("%s: DLOPEN successful for %s", __func__, LIB_CSD_CLIENT);
370
371        csd->deinit = (deinit_t)dlsym(csd->csd_client,
372                                             "csd_client_deinit");
373        if (csd->deinit == NULL) {
374            ALOGE("%s: dlsym error %s for csd_client_deinit", __func__,
375                  dlerror());
376            goto error;
377        }
378        csd->disable_device = (disable_device_t)dlsym(csd->csd_client,
379                                             "csd_client_disable_device");
380        if (csd->disable_device == NULL) {
381            ALOGE("%s: dlsym error %s for csd_client_disable_device",
382                  __func__, dlerror());
383            goto error;
384        }
385        csd->enable_device_config = (enable_device_config_t)dlsym(csd->csd_client,
386                                               "csd_client_enable_device_config");
387        if (csd->enable_device_config == NULL) {
388            ALOGE("%s: dlsym error %s for csd_client_enable_device_config",
389                  __func__, dlerror());
390            goto error;
391        }
392        csd->enable_device = (enable_device_t)dlsym(csd->csd_client,
393                                             "csd_client_enable_device");
394        if (csd->enable_device == NULL) {
395            ALOGE("%s: dlsym error %s for csd_client_enable_device",
396                  __func__, dlerror());
397            goto error;
398        }
399        csd->start_voice = (start_voice_t)dlsym(csd->csd_client,
400                                             "csd_client_start_voice");
401        if (csd->start_voice == NULL) {
402            ALOGE("%s: dlsym error %s for csd_client_start_voice",
403                  __func__, dlerror());
404            goto error;
405        }
406        csd->stop_voice = (stop_voice_t)dlsym(csd->csd_client,
407                                             "csd_client_stop_voice");
408        if (csd->stop_voice == NULL) {
409            ALOGE("%s: dlsym error %s for csd_client_stop_voice",
410                  __func__, dlerror());
411            goto error;
412        }
413        csd->volume = (volume_t)dlsym(csd->csd_client,
414                                             "csd_client_volume");
415        if (csd->volume == NULL) {
416            ALOGE("%s: dlsym error %s for csd_client_volume",
417                  __func__, dlerror());
418            goto error;
419        }
420        csd->mic_mute = (mic_mute_t)dlsym(csd->csd_client,
421                                             "csd_client_mic_mute");
422        if (csd->mic_mute == NULL) {
423            ALOGE("%s: dlsym error %s for csd_client_mic_mute",
424                  __func__, dlerror());
425            goto error;
426        }
427        csd->slow_talk = (slow_talk_t)dlsym(csd->csd_client,
428                                             "csd_client_slow_talk");
429        if (csd->slow_talk == NULL) {
430            ALOGE("%s: dlsym error %s for csd_client_slow_talk",
431                  __func__, dlerror());
432            goto error;
433        }
434        csd->start_playback = (start_playback_t)dlsym(csd->csd_client,
435                                             "csd_client_start_playback");
436        if (csd->start_playback == NULL) {
437            ALOGE("%s: dlsym error %s for csd_client_start_playback",
438                  __func__, dlerror());
439            goto error;
440        }
441        csd->stop_playback = (stop_playback_t)dlsym(csd->csd_client,
442                                             "csd_client_stop_playback");
443        if (csd->stop_playback == NULL) {
444            ALOGE("%s: dlsym error %s for csd_client_stop_playback",
445                  __func__, dlerror());
446            goto error;
447        }
448        csd->start_record = (start_record_t)dlsym(csd->csd_client,
449                                             "csd_client_start_record");
450        if (csd->start_record == NULL) {
451            ALOGE("%s: dlsym error %s for csd_client_start_record",
452                  __func__, dlerror());
453            goto error;
454        }
455        csd->stop_record = (stop_record_t)dlsym(csd->csd_client,
456                                             "csd_client_stop_record");
457        if (csd->stop_record == NULL) {
458            ALOGE("%s: dlsym error %s for csd_client_stop_record",
459                  __func__, dlerror());
460            goto error;
461        }
462
463        csd->get_sample_rate = (get_sample_rate_t)dlsym(csd->csd_client,
464                                             "csd_client_get_sample_rate");
465        if (csd->get_sample_rate == NULL) {
466            ALOGE("%s: dlsym error %s for csd_client_get_sample_rate",
467                  __func__, dlerror());
468
469            goto error;
470        }
471
472        csd->init = (init_t)dlsym(csd->csd_client, "csd_client_init");
473
474        if (csd->init == NULL) {
475            ALOGE("%s: dlsym error %s for csd_client_init",
476                  __func__, dlerror());
477            goto error;
478        } else {
479            csd->init(i2s_ext_modem);
480        }
481    }
482    return csd;
483
484error:
485    free(csd);
486    csd = NULL;
487    return csd;
488}
489
490void close_csd_client(struct csd_data *csd)
491{
492    if (csd != NULL) {
493        csd->deinit();
494        dlclose(csd->csd_client);
495        free(csd);
496        csd = NULL;
497    }
498}
499
500static void platform_csd_init(struct platform_data *my_data)
501{
502#ifdef PLATFORM_MSM8084
503    struct dev_info mdm_detect_info;
504    int ret = 0;
505
506    /* Call ESOC API to get the number of modems.
507     * If the number of modems is not zero, load CSD Client specific
508     * symbols. Voice call is handled by MDM and apps processor talks to
509     * MDM through CSD Client
510     */
511    ret = get_system_info(&mdm_detect_info);
512    if (ret > 0) {
513        ALOGE("%s: Failed to get system info, ret %d", __func__, ret);
514    }
515    ALOGD("%s: num_modems %d\n", __func__, mdm_detect_info.num_modems);
516
517    if (mdm_detect_info.num_modems > 0)
518        my_data->csd = open_csd_client(false /*is_i2s_ext_modem*/);
519#else
520     my_data->csd = NULL;
521#endif
522}
523
524static void set_platform_defaults(struct platform_data * my_data)
525{
526    int32_t dev;
527    for (dev = 0; dev < SND_DEVICE_MAX; dev++) {
528        backend_table[dev] = NULL;
529    }
530
531    // TBD - do these go to the platform-info.xml file.
532    // will help in avoiding strdups here
533    backend_table[SND_DEVICE_IN_BT_SCO_MIC] = strdup("bt-sco");
534    backend_table[SND_DEVICE_OUT_BT_SCO] = strdup("bt-sco");
535    backend_table[SND_DEVICE_OUT_HDMI] = strdup("hdmi");
536    backend_table[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = strdup("speaker-and-hdmi");
537    backend_table[SND_DEVICE_OUT_BT_SCO_WB] = strdup("bt-sco-wb");
538    backend_table[SND_DEVICE_IN_BT_SCO_MIC_WB] = strdup("bt-sco-wb");
539
540    if (my_data->ext_speaker) {
541        backend_table[SND_DEVICE_OUT_SPEAKER] = strdup("speaker");
542        backend_table[SND_DEVICE_OUT_VOICE_SPEAKER] = strdup("speaker");
543        backend_table[SND_DEVICE_OUT_SPEAKER_REVERSE] = strdup("speaker");
544        backend_table[SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] =
545            strdup("speaker-and-headphones");
546    }
547
548    if (my_data->ext_earpiece) {
549        backend_table[SND_DEVICE_OUT_VOICE_HANDSET] = strdup("handset");
550        backend_table[SND_DEVICE_OUT_VOICE_HAC_HANDSET] = strdup("handset");
551        backend_table[SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = strdup("handset");
552        backend_table[SND_DEVICE_OUT_HANDSET] = strdup("handset");
553        backend_table[SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = strdup("handset");
554    }
555}
556
557void *platform_init(struct audio_device *adev)
558{
559    char value[PROPERTY_VALUE_MAX];
560    struct platform_data *my_data;
561    int retry_num = 0, snd_card_num = 0;
562    const char *snd_card_name;
563
564    while (snd_card_num < MAX_SND_CARD) {
565        adev->mixer = mixer_open(snd_card_num);
566
567        while (!adev->mixer && retry_num < RETRY_NUMBER) {
568            usleep(RETRY_US);
569            adev->mixer = mixer_open(snd_card_num);
570            retry_num++;
571        }
572
573        if (!adev->mixer) {
574            ALOGE("%s: Unable to open the mixer card: %d", __func__,
575                   snd_card_num);
576            retry_num = 0;
577            snd_card_num++;
578            continue;
579        }
580
581        snd_card_name = mixer_get_name(adev->mixer);
582        ALOGD("%s: snd_card_name: %s", __func__, snd_card_name);
583
584        adev->audio_route = audio_route_init(snd_card_num, MIXER_XML_PATH);
585        if (!adev->audio_route) {
586            ALOGE("%s: Failed to init audio route controls, aborting.", __func__);
587            return NULL;
588        }
589        adev->snd_card = snd_card_num;
590        ALOGD("%s: Opened sound card:%d", __func__, snd_card_num);
591        break;
592    }
593
594    if (snd_card_num >= MAX_SND_CARD) {
595        ALOGE("%s: Unable to find correct sound card, aborting.", __func__);
596        return NULL;
597    }
598
599    my_data = calloc(1, sizeof(struct platform_data));
600
601    my_data->adev = adev;
602    my_data->dualmic_config = DUALMIC_CONFIG_NONE;
603    my_data->fluence_in_spkr_mode = false;
604    my_data->fluence_in_voice_call = false;
605    my_data->fluence_in_voice_rec = false;
606
607    /*
608     * The default assumption is that earpiece (handset), speaker and headphones
609     * devices are connected to internal HW codec and communicated through
610     * slimbus backend. If any platform communicates with speaker or earpiece
611     * or headphones through non-slimbus backend such as MI2S or AUXPCM etc.,
612     * the ext_xxxx flags must be set accordingly.
613     */
614    if (strstr(snd_card_name, "tfa9890_stereo")) {
615        my_data->ext_speaker = true;
616        my_data->ext_earpiece = true;
617    } else if (strstr(snd_card_name, "tfa9890")) {
618        my_data->ext_speaker = true;
619    }
620
621    property_get("persist.audio.dualmic.config",value,"");
622    if (!strcmp("broadside", value)) {
623        my_data->dualmic_config = DUALMIC_CONFIG_BROADSIDE;
624        adev->acdb_settings |= DMIC_FLAG;
625    } else if (!strcmp("endfire", value)) {
626        my_data->dualmic_config = DUALMIC_CONFIG_ENDFIRE;
627        adev->acdb_settings |= DMIC_FLAG;
628    }
629
630    if (my_data->dualmic_config != DUALMIC_CONFIG_NONE) {
631        property_get("persist.audio.fluence.voicecall",value,"");
632        if (!strcmp("true", value)) {
633            my_data->fluence_in_voice_call = true;
634        }
635
636        property_get("persist.audio.fluence.voicerec",value,"");
637        if (!strcmp("true", value)) {
638            my_data->fluence_in_voice_rec = true;
639        }
640
641        property_get("persist.audio.fluence.speaker",value,"");
642        if (!strcmp("true", value)) {
643            my_data->fluence_in_spkr_mode = true;
644        }
645    }
646
647    my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
648    if (my_data->acdb_handle == NULL) {
649        ALOGE("%s: DLOPEN failed for %s", __func__, LIB_ACDB_LOADER);
650    } else {
651        ALOGV("%s: DLOPEN successful for %s", __func__, LIB_ACDB_LOADER);
652        my_data->acdb_deallocate = (acdb_deallocate_t)dlsym(my_data->acdb_handle,
653                                                    "acdb_loader_deallocate_ACDB");
654        if (!my_data->acdb_deallocate)
655            ALOGE("%s: Could not find the symbol acdb_loader_deallocate_ACDB from %s",
656                  __func__, LIB_ACDB_LOADER);
657
658        my_data->acdb_send_audio_cal = (acdb_send_audio_cal_t)dlsym(my_data->acdb_handle,
659                                                    "acdb_loader_send_audio_cal");
660        if (!my_data->acdb_send_audio_cal)
661            ALOGE("%s: Could not find the symbol acdb_send_audio_cal from %s",
662                  __func__, LIB_ACDB_LOADER);
663
664        my_data->acdb_send_voice_cal = (acdb_send_voice_cal_t)dlsym(my_data->acdb_handle,
665                                                    "acdb_loader_send_voice_cal");
666        if (!my_data->acdb_send_voice_cal)
667            ALOGE("%s: Could not find the symbol acdb_loader_send_voice_cal from %s",
668                  __func__, LIB_ACDB_LOADER);
669
670        my_data->acdb_reload_vocvoltable = (acdb_reload_vocvoltable_t)dlsym(my_data->acdb_handle,
671                                                    "acdb_loader_reload_vocvoltable");
672        if (!my_data->acdb_reload_vocvoltable)
673            ALOGE("%s: Could not find the symbol acdb_loader_reload_vocvoltable from %s",
674                  __func__, LIB_ACDB_LOADER);
675#ifdef PLATFORM_MSM8084
676        my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
677                                                    "acdb_loader_init_v2");
678        if (my_data->acdb_init == NULL)
679            ALOGE("%s: dlsym error %s for acdb_loader_init_v2", __func__, dlerror());
680        else
681            my_data->acdb_init((char *)snd_card_name);
682#else
683        my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
684                                                    "acdb_loader_init_ACDB");
685        if (my_data->acdb_init == NULL)
686            ALOGE("%s: dlsym error %s for acdb_loader_init_ACDB", __func__, dlerror());
687        else
688            my_data->acdb_init();
689#endif
690
691    }
692
693    set_platform_defaults(my_data);
694
695    /* Initialize platform specific ids and/or backends*/
696    platform_info_init();
697
698    /* load csd client */
699    platform_csd_init(my_data);
700
701    return my_data;
702}
703
704void platform_deinit(void *platform)
705{
706    struct platform_data *my_data = (struct platform_data *)platform;
707    close_csd_client(my_data->csd);
708    free(platform);
709}
710
711const char *platform_get_snd_device_name(snd_device_t snd_device)
712{
713    if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX)
714        return device_table[snd_device];
715    else
716        return "";
717}
718
719void platform_add_backend_name(void *platform, char *mixer_path,
720                               snd_device_t snd_device)
721{
722    struct platform_data *my_data = (struct platform_data *)platform;
723
724    if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) {
725        ALOGE("%s: Invalid snd_device = %d", __func__, snd_device);
726        return;
727    }
728
729    const char * suffix = backend_table[snd_device];
730
731    if (suffix != NULL) {
732        strcat(mixer_path, " ");
733        strcat(mixer_path, suffix);
734    }
735}
736
737int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type)
738{
739    int device_id;
740    if (device_type == PCM_PLAYBACK)
741        device_id = pcm_device_table[usecase][0];
742    else
743        device_id = pcm_device_table[usecase][1];
744    return device_id;
745}
746
747static int find_index(const struct name_to_index * table, int32_t len,
748                      const char * name)
749{
750    int ret = 0;
751    int32_t i;
752
753    if (table == NULL) {
754        ALOGE("%s: table is NULL", __func__);
755        ret = -ENODEV;
756        goto done;
757    }
758
759    if (name == NULL) {
760        ALOGE("null key");
761        ret = -ENODEV;
762        goto done;
763    }
764
765    for (i=0; i < len; i++) {
766        if (!strcmp(table[i].name, name)) {
767            ret = table[i].index;
768            goto done;
769        }
770    }
771    ALOGE("%s: Could not find index for name = %s",
772            __func__, name);
773    ret = -ENODEV;
774done:
775    return ret;
776}
777
778int platform_get_snd_device_index(char *device_name)
779{
780    return find_index(snd_device_name_index, SND_DEVICE_MAX, device_name);
781}
782
783int platform_get_usecase_index(const char *usecase_name)
784{
785    return find_index(usecase_name_index, AUDIO_USECASE_MAX, usecase_name);
786}
787
788int platform_set_snd_device_acdb_id(snd_device_t snd_device, unsigned int acdb_id)
789{
790    int ret = 0;
791
792    if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) {
793        ALOGE("%s: Invalid snd_device = %d",
794            __func__, snd_device);
795        ret = -EINVAL;
796        goto done;
797    }
798
799    acdb_device_table[snd_device] = acdb_id;
800done:
801    return ret;
802}
803
804int platform_send_audio_calibration(void *platform, snd_device_t snd_device)
805{
806    struct platform_data *my_data = (struct platform_data *)platform;
807    int acdb_dev_id, acdb_dev_type;
808
809    acdb_dev_id = acdb_device_table[snd_device];
810    if (acdb_dev_id < 0) {
811        ALOGE("%s: Could not find acdb id for device(%d)",
812              __func__, snd_device);
813        return -EINVAL;
814    }
815    if (my_data->acdb_send_audio_cal) {
816        ("%s: sending audio calibration for snd_device(%d) acdb_id(%d)",
817              __func__, snd_device, acdb_dev_id);
818        if (snd_device >= SND_DEVICE_OUT_BEGIN &&
819                snd_device < SND_DEVICE_OUT_END)
820            acdb_dev_type = ACDB_DEV_TYPE_OUT;
821        else
822            acdb_dev_type = ACDB_DEV_TYPE_IN;
823        my_data->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type);
824    }
825    return 0;
826}
827
828int platform_switch_voice_call_device_pre(void *platform)
829{
830    struct platform_data *my_data = (struct platform_data *)platform;
831    int ret = 0;
832
833    if (my_data->csd != NULL &&
834        my_data->adev->mode == AUDIO_MODE_IN_CALL) {
835        /* This must be called before disabling mixer controls on APQ side */
836        ret = my_data->csd->disable_device();
837        if (ret < 0) {
838            ALOGE("%s: csd_client_disable_device, failed, error %d",
839                  __func__, ret);
840        }
841    }
842    return ret;
843}
844
845int platform_switch_voice_call_enable_device_config(void *platform,
846                                                    snd_device_t out_snd_device,
847                                                    snd_device_t in_snd_device)
848{
849    struct platform_data *my_data = (struct platform_data *)platform;
850    int acdb_rx_id, acdb_tx_id;
851    int ret = 0;
852
853    if (my_data->csd == NULL)
854        return ret;
855
856    acdb_rx_id = acdb_device_table[out_snd_device];
857
858    acdb_tx_id = acdb_device_table[in_snd_device];
859
860    if (acdb_rx_id > 0 && acdb_tx_id > 0) {
861        ret = my_data->csd->enable_device_config(acdb_rx_id, acdb_tx_id);
862        if (ret < 0) {
863            ALOGE("%s: csd_enable_device_config, failed, error %d",
864                  __func__, ret);
865        }
866    } else {
867        ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__,
868              acdb_rx_id, acdb_tx_id);
869    }
870
871    return ret;
872}
873
874int platform_switch_voice_call_device_post(void *platform,
875                                           snd_device_t out_snd_device,
876                                           snd_device_t in_snd_device)
877{
878    struct platform_data *my_data = (struct platform_data *)platform;
879    int acdb_rx_id, acdb_tx_id;
880
881    if (my_data->acdb_send_voice_cal == NULL) {
882        ALOGE("%s: dlsym error for acdb_send_voice_call", __func__);
883    } else {
884        acdb_rx_id = acdb_device_table[out_snd_device];
885        acdb_tx_id = acdb_device_table[in_snd_device];
886
887        if (acdb_rx_id > 0 && acdb_tx_id > 0)
888            my_data->acdb_send_voice_cal(acdb_rx_id, acdb_tx_id);
889        else
890            ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__,
891                  acdb_rx_id, acdb_tx_id);
892    }
893
894    return 0;
895}
896
897int platform_switch_voice_call_usecase_route_post(void *platform,
898                                                  snd_device_t out_snd_device,
899                                                  snd_device_t in_snd_device)
900{
901    struct platform_data *my_data = (struct platform_data *)platform;
902    int acdb_rx_id, acdb_tx_id;
903    int ret = 0;
904
905    if (my_data->csd == NULL)
906        return ret;
907
908    acdb_rx_id = acdb_device_table[out_snd_device];
909
910    acdb_tx_id = acdb_device_table[in_snd_device];
911
912    if (acdb_rx_id > 0 && acdb_tx_id > 0) {
913        ret = my_data->csd->enable_device(acdb_rx_id, acdb_tx_id,
914                                          my_data->adev->acdb_settings);
915        if (ret < 0) {
916            ALOGE("%s: csd_enable_device, failed, error %d", __func__, ret);
917        }
918    } else {
919        ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__,
920              acdb_rx_id, acdb_tx_id);
921    }
922
923    return ret;
924}
925
926int platform_start_voice_call(void *platform, uint32_t vsid)
927{
928    struct platform_data *my_data = (struct platform_data *)platform;
929    int ret = 0;
930
931    if (my_data->csd != NULL) {
932        ret = my_data->csd->start_voice(vsid);
933        if (ret < 0) {
934            ALOGE("%s: csd_start_voice error %d\n", __func__, ret);
935        }
936    }
937    return ret;
938}
939
940int platform_stop_voice_call(void *platform, uint32_t vsid)
941{
942    struct platform_data *my_data = (struct platform_data *)platform;
943    int ret = 0;
944
945    if (my_data->csd != NULL) {
946        ret = my_data->csd->stop_voice(vsid);
947        if (ret < 0) {
948            ALOGE("%s: csd_stop_voice error %d\n", __func__, ret);
949        }
950    }
951    return ret;
952}
953
954int platform_get_sample_rate(void *platform, uint32_t *rate)
955{
956    struct platform_data *my_data = (struct platform_data *)platform;
957    int ret = 0;
958
959    if (my_data->csd != NULL) {
960        ret = my_data->csd->get_sample_rate(rate);
961        if (ret < 0) {
962            ALOGE("%s: csd_get_sample_rate error %d\n", __func__, ret);
963        }
964    }
965    return ret;
966}
967
968int platform_set_voice_volume(void *platform, int volume)
969{
970    struct platform_data *my_data = (struct platform_data *)platform;
971    struct audio_device *adev = my_data->adev;
972    struct mixer_ctl *ctl;
973    const char *mixer_ctl_name = "Voice Rx Gain";
974    int vol_index = 0, ret = 0;
975    uint32_t set_values[ ] = {0,
976                              ALL_SESSION_VSID,
977                              DEFAULT_VOLUME_RAMP_DURATION_MS};
978
979    // Voice volume levels are mapped to adsp volume levels as follows.
980    // 100 -> 5, 80 -> 4, 60 -> 3, 40 -> 2, 20 -> 1  0 -> 0
981    // But this values don't changed in kernel. So, below change is need.
982    vol_index = (int)percent_to_index(volume, MIN_VOL_INDEX, MAX_VOL_INDEX);
983    set_values[0] = vol_index;
984
985    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
986    if (!ctl) {
987        ALOGE("%s: Could not get ctl for mixer cmd - %s",
988              __func__, mixer_ctl_name);
989        return -EINVAL;
990    }
991    ALOGV("Setting voice volume index: %d", set_values[0]);
992    mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
993
994    if (my_data->csd != NULL) {
995        ret = my_data->csd->volume(ALL_SESSION_VSID, volume,
996                                   DEFAULT_VOLUME_RAMP_DURATION_MS);
997        if (ret < 0) {
998            ALOGE("%s: csd_volume error %d", __func__, ret);
999        }
1000    }
1001    return ret;
1002}
1003
1004int platform_set_mic_mute(void *platform, bool state)
1005{
1006    struct platform_data *my_data = (struct platform_data *)platform;
1007    struct audio_device *adev = my_data->adev;
1008    struct mixer_ctl *ctl;
1009    const char *mixer_ctl_name = "Voice Tx Mute";
1010    int ret = 0;
1011    uint32_t set_values[ ] = {0,
1012                              ALL_SESSION_VSID,
1013                              DEFAULT_MUTE_RAMP_DURATION_MS};
1014
1015    if (adev->mode != AUDIO_MODE_IN_CALL)
1016        return 0;
1017
1018    set_values[0] = state;
1019    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1020    if (!ctl) {
1021        ALOGE("%s: Could not get ctl for mixer cmd - %s",
1022              __func__, mixer_ctl_name);
1023        return -EINVAL;
1024    }
1025    ALOGV("Setting voice mute state: %d", state);
1026    mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1027
1028    if (my_data->csd != NULL) {
1029        ret = my_data->csd->mic_mute(ALL_SESSION_VSID, state,
1030                                     DEFAULT_MUTE_RAMP_DURATION_MS);
1031        if (ret < 0) {
1032            ALOGE("%s: csd_mic_mute error %d", __func__, ret);
1033        }
1034    }
1035    return ret;
1036}
1037
1038int platform_set_device_mute(void *platform, bool state, char *dir)
1039{
1040    struct platform_data *my_data = (struct platform_data *)platform;
1041    struct audio_device *adev = my_data->adev;
1042    struct mixer_ctl *ctl;
1043    char *mixer_ctl_name = NULL;
1044    int ret = 0;
1045    uint32_t set_values[ ] = {0,
1046                              ALL_SESSION_VSID,
1047                              0};
1048    if(dir == NULL) {
1049        ALOGE("%s: Invalid direction:%s", __func__, dir);
1050        return -EINVAL;
1051    }
1052
1053    if (!strncmp("rx", dir, sizeof("rx"))) {
1054        mixer_ctl_name = "Voice Rx Device Mute";
1055    } else if (!strncmp("tx", dir, sizeof("tx"))) {
1056        mixer_ctl_name = "Voice Tx Device Mute";
1057    } else {
1058        return -EINVAL;
1059    }
1060
1061    set_values[0] = state;
1062    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1063    if (!ctl) {
1064        ALOGE("%s: Could not get ctl for mixer cmd - %s",
1065              __func__, mixer_ctl_name);
1066        return -EINVAL;
1067    }
1068
1069    ALOGV("%s: Setting device mute state: %d, mixer ctrl:%s",
1070          __func__,state, mixer_ctl_name);
1071    mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1072
1073    return ret;
1074}
1075
1076snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices)
1077{
1078    struct platform_data *my_data = (struct platform_data *)platform;
1079    struct audio_device *adev = my_data->adev;
1080    audio_mode_t mode = adev->mode;
1081    snd_device_t snd_device = SND_DEVICE_NONE;
1082
1083    ALOGV("%s: enter: output devices(%#x)", __func__, devices);
1084    if (devices == AUDIO_DEVICE_NONE ||
1085        devices & AUDIO_DEVICE_BIT_IN) {
1086        ALOGV("%s: Invalid output devices (%#x)", __func__, devices);
1087        goto exit;
1088    }
1089
1090    if (mode == AUDIO_MODE_IN_CALL) {
1091        if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
1092            devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
1093            if (adev->voice.tty_mode == TTY_MODE_FULL)
1094                snd_device = SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES;
1095            else if (adev->voice.tty_mode == TTY_MODE_VCO)
1096                snd_device = SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES;
1097            else if (adev->voice.tty_mode == TTY_MODE_HCO)
1098                snd_device = SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET;
1099            else
1100                snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES;
1101        } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
1102            if (adev->bt_wb_speech_enabled) {
1103                snd_device = SND_DEVICE_OUT_BT_SCO_WB;
1104            } else {
1105                snd_device = SND_DEVICE_OUT_BT_SCO;
1106            }
1107        } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
1108            snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
1109        } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
1110            if(adev->voice.hac)
1111                snd_device = SND_DEVICE_OUT_VOICE_HAC_HANDSET;
1112            else if (is_operator_tmus())
1113                snd_device = SND_DEVICE_OUT_VOICE_HANDSET_TMUS;
1114            else
1115                snd_device = SND_DEVICE_OUT_VOICE_HANDSET;
1116        }
1117        if (snd_device != SND_DEVICE_NONE) {
1118            goto exit;
1119        }
1120    }
1121
1122    if (popcount(devices) == 2) {
1123        if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
1124                        AUDIO_DEVICE_OUT_SPEAKER)) {
1125            snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
1126        } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
1127                               AUDIO_DEVICE_OUT_SPEAKER)) {
1128            snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
1129        } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL |
1130                               AUDIO_DEVICE_OUT_SPEAKER)) {
1131            snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
1132        } else {
1133            ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
1134            goto exit;
1135        }
1136        if (snd_device != SND_DEVICE_NONE) {
1137            goto exit;
1138        }
1139    }
1140
1141    if (popcount(devices) != 1) {
1142        ALOGE("%s: Invalid output devices(%#x)", __func__, devices);
1143        goto exit;
1144    }
1145
1146    if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
1147        devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
1148        snd_device = SND_DEVICE_OUT_HEADPHONES;
1149    } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
1150        if (adev->speaker_lr_swap)
1151            snd_device = SND_DEVICE_OUT_SPEAKER_REVERSE;
1152        else
1153            snd_device = SND_DEVICE_OUT_SPEAKER;
1154    } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
1155        if (adev->bt_wb_speech_enabled) {
1156            snd_device = SND_DEVICE_OUT_BT_SCO_WB;
1157        } else {
1158            snd_device = SND_DEVICE_OUT_BT_SCO;
1159        }
1160    } else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1161        snd_device = SND_DEVICE_OUT_HDMI ;
1162    } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
1163        /*HAC support for voice-ish audio (eg visual voicemail)*/
1164        if(adev->voice.hac)
1165            snd_device = SND_DEVICE_OUT_VOICE_HAC_HANDSET;
1166        else
1167            snd_device = SND_DEVICE_OUT_HANDSET;
1168    } else {
1169        ALOGE("%s: Unknown device(s) %#x", __func__, devices);
1170    }
1171exit:
1172    ALOGV("%s: exit: snd_device(%s)", __func__, device_table[snd_device]);
1173    return snd_device;
1174}
1175
1176snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device)
1177{
1178    struct platform_data *my_data = (struct platform_data *)platform;
1179    struct audio_device *adev = my_data->adev;
1180    audio_source_t  source = (adev->active_input == NULL) ?
1181                                AUDIO_SOURCE_DEFAULT : adev->active_input->source;
1182
1183    audio_mode_t    mode   = adev->mode;
1184    audio_devices_t in_device = ((adev->active_input == NULL) ?
1185                                    AUDIO_DEVICE_NONE : adev->active_input->device)
1186                                & ~AUDIO_DEVICE_BIT_IN;
1187    audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
1188                                AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
1189    snd_device_t snd_device = SND_DEVICE_NONE;
1190
1191    ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
1192          __func__, out_device, in_device);
1193    if (mode == AUDIO_MODE_IN_CALL) {
1194        if (out_device == AUDIO_DEVICE_NONE) {
1195            ALOGE("%s: No output device set for voice call", __func__);
1196            goto exit;
1197        }
1198        if (adev->voice.tty_mode != TTY_MODE_OFF) {
1199            if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
1200                out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
1201                switch (adev->voice.tty_mode) {
1202                case TTY_MODE_FULL:
1203                    snd_device = SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC;
1204                    break;
1205                case TTY_MODE_VCO:
1206                    snd_device = SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC;
1207                    break;
1208                case TTY_MODE_HCO:
1209                    snd_device = SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC;
1210                    break;
1211                default:
1212                    ALOGE("%s: Invalid TTY mode (%#x)", __func__, adev->voice.tty_mode);
1213                }
1214                goto exit;
1215            }
1216        }
1217        if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
1218            out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
1219            if (my_data->fluence_in_voice_call == false) {
1220                snd_device = SND_DEVICE_IN_HANDSET_MIC;
1221                set_echo_reference(adev->mixer, "SLIM_RX");
1222            } else {
1223                if (my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
1224                    if (is_operator_tmus())
1225                        snd_device = SND_DEVICE_IN_VOICE_DMIC_EF_TMUS;
1226                    else
1227                        snd_device = SND_DEVICE_IN_VOICE_DMIC_EF;
1228                } else if(my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE)
1229                    snd_device = SND_DEVICE_IN_VOICE_DMIC_BS;
1230                else
1231                    snd_device = SND_DEVICE_IN_HANDSET_MIC;
1232            }
1233        } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
1234            snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
1235        } else if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
1236            if (adev->bt_wb_speech_enabled) {
1237                snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
1238            } else {
1239                snd_device = SND_DEVICE_IN_BT_SCO_MIC;
1240            }
1241        } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
1242            if (my_data->fluence_in_voice_call && my_data->fluence_in_spkr_mode &&
1243                    my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
1244                snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF;
1245            } else if (my_data->fluence_in_voice_call && my_data->fluence_in_spkr_mode &&
1246                    my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE) {
1247                snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS;
1248            } else {
1249                snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
1250            }
1251        }
1252    } else if (source == AUDIO_SOURCE_CAMCORDER) {
1253        if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
1254            in_device & AUDIO_DEVICE_IN_BACK_MIC) {
1255            snd_device = SND_DEVICE_IN_CAMCORDER_MIC;
1256        }
1257    } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) {
1258        if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
1259            if (my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
1260                if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
1261                    snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_EF;
1262                else if (my_data->fluence_in_voice_rec)
1263                    snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE;
1264            } else if (my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE) {
1265                if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
1266                    snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_BS;
1267                else if (my_data->fluence_in_voice_rec)
1268                    snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE;
1269            }
1270
1271            if (snd_device == SND_DEVICE_NONE) {
1272                snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
1273            }
1274        }
1275    } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1276        if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
1277            in_device = AUDIO_DEVICE_IN_BACK_MIC;
1278        if (adev->active_input) {
1279            if (adev->active_input->enable_aec) {
1280                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
1281                    snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
1282                } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
1283                    snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
1284                } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
1285                    snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
1286                }
1287                set_echo_reference(adev->mixer, "SLIM_RX");
1288            } else
1289                set_echo_reference(adev->mixer, "NONE");
1290        }
1291    } else if (source == AUDIO_SOURCE_DEFAULT) {
1292        goto exit;
1293    }
1294
1295
1296    if (snd_device != SND_DEVICE_NONE) {
1297        goto exit;
1298    }
1299
1300    if (in_device != AUDIO_DEVICE_NONE &&
1301            !(in_device & AUDIO_DEVICE_IN_VOICE_CALL) &&
1302            !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) {
1303        if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
1304            snd_device = SND_DEVICE_IN_HANDSET_MIC;
1305        } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
1306            snd_device = SND_DEVICE_IN_SPEAKER_MIC;
1307        } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
1308            snd_device = SND_DEVICE_IN_HEADSET_MIC;
1309        } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
1310            if (adev->bt_wb_speech_enabled) {
1311                snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
1312            } else {
1313                snd_device = SND_DEVICE_IN_BT_SCO_MIC;
1314            }
1315        } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) {
1316            snd_device = SND_DEVICE_IN_HDMI_MIC;
1317        } else {
1318            ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
1319            ALOGW("%s: Using default handset-mic", __func__);
1320            snd_device = SND_DEVICE_IN_HANDSET_MIC;
1321        }
1322    } else {
1323        if (out_device & AUDIO_DEVICE_OUT_EARPIECE) {
1324            snd_device = SND_DEVICE_IN_HANDSET_MIC;
1325        } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
1326            snd_device = SND_DEVICE_IN_HEADSET_MIC;
1327        } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
1328            snd_device = SND_DEVICE_IN_SPEAKER_MIC;
1329        } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
1330            snd_device = SND_DEVICE_IN_HANDSET_MIC;
1331        } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
1332            if (adev->bt_wb_speech_enabled) {
1333                snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
1334            } else {
1335                snd_device = SND_DEVICE_IN_BT_SCO_MIC;
1336            }
1337        } else if (out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1338            snd_device = SND_DEVICE_IN_HDMI_MIC;
1339        } else {
1340            ALOGE("%s: Unknown output device(s) %#x", __func__, out_device);
1341            ALOGW("%s: Using default handset-mic", __func__);
1342            snd_device = SND_DEVICE_IN_HANDSET_MIC;
1343        }
1344    }
1345exit:
1346    ALOGV("%s: exit: in_snd_device(%s)", __func__, device_table[snd_device]);
1347    return snd_device;
1348}
1349
1350int platform_set_hdmi_channels(void *platform,  int channel_count)
1351{
1352    struct platform_data *my_data = (struct platform_data *)platform;
1353    struct audio_device *adev = my_data->adev;
1354    struct mixer_ctl *ctl;
1355    const char *channel_cnt_str = NULL;
1356    const char *mixer_ctl_name = "HDMI_RX Channels";
1357    switch (channel_count) {
1358    case 8:
1359        channel_cnt_str = "Eight"; break;
1360    case 7:
1361        channel_cnt_str = "Seven"; break;
1362    case 6:
1363        channel_cnt_str = "Six"; break;
1364    case 5:
1365        channel_cnt_str = "Five"; break;
1366    case 4:
1367        channel_cnt_str = "Four"; break;
1368    case 3:
1369        channel_cnt_str = "Three"; break;
1370    default:
1371        channel_cnt_str = "Two"; break;
1372    }
1373    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1374    if (!ctl) {
1375        ALOGE("%s: Could not get ctl for mixer cmd - %s",
1376              __func__, mixer_ctl_name);
1377        return -EINVAL;
1378    }
1379    ALOGV("HDMI channel count: %s", channel_cnt_str);
1380    mixer_ctl_set_enum_by_string(ctl, channel_cnt_str);
1381    return 0;
1382}
1383
1384int platform_edid_get_max_channels(void *platform)
1385{
1386    struct platform_data *my_data = (struct platform_data *)platform;
1387    struct audio_device *adev = my_data->adev;
1388    char block[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE];
1389    char *sad = block;
1390    int num_audio_blocks;
1391    int channel_count;
1392    int max_channels = 0;
1393    int i, ret, count;
1394
1395    struct mixer_ctl *ctl;
1396
1397    ctl = mixer_get_ctl_by_name(adev->mixer, AUDIO_DATA_BLOCK_MIXER_CTL);
1398    if (!ctl) {
1399        ALOGE("%s: Could not get ctl for mixer cmd - %s",
1400              __func__, AUDIO_DATA_BLOCK_MIXER_CTL);
1401        return 0;
1402    }
1403
1404    mixer_ctl_update(ctl);
1405
1406    count = mixer_ctl_get_num_values(ctl);
1407
1408    /* Read SAD blocks, clamping the maximum size for safety */
1409    if (count > (int)sizeof(block))
1410        count = (int)sizeof(block);
1411
1412    ret = mixer_ctl_get_array(ctl, block, count);
1413    if (ret != 0) {
1414        ALOGE("%s: mixer_ctl_get_array() failed to get EDID info", __func__);
1415        return 0;
1416    }
1417
1418    /* Calculate the number of SAD blocks */
1419    num_audio_blocks = count / SAD_BLOCK_SIZE;
1420
1421    for (i = 0; i < num_audio_blocks; i++) {
1422        /* Only consider LPCM blocks */
1423        if ((sad[0] >> 3) != EDID_FORMAT_LPCM) {
1424            sad += 3;
1425            continue;
1426        }
1427
1428        channel_count = (sad[0] & 0x7) + 1;
1429        if (channel_count > max_channels)
1430            max_channels = channel_count;
1431
1432        /* Advance to next block */
1433        sad += 3;
1434    }
1435
1436    return max_channels;
1437}
1438
1439int platform_set_incall_recording_session_id(void *platform,
1440                                             uint32_t session_id, int rec_mode)
1441{
1442    int ret = 0;
1443    struct platform_data *my_data = (struct platform_data *)platform;
1444    struct audio_device *adev = my_data->adev;
1445    struct mixer_ctl *ctl;
1446    const char *mixer_ctl_name = "Voc VSID";
1447    int num_ctl_values;
1448    int i;
1449
1450    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1451    if (!ctl) {
1452        ALOGE("%s: Could not get ctl for mixer cmd - %s",
1453              __func__, mixer_ctl_name);
1454        ret = -EINVAL;
1455    } else {
1456        num_ctl_values = mixer_ctl_get_num_values(ctl);
1457        for (i = 0; i < num_ctl_values; i++) {
1458            if (mixer_ctl_set_value(ctl, i, session_id)) {
1459                ALOGV("Error: invalid session_id: %x", session_id);
1460                ret = -EINVAL;
1461                break;
1462            }
1463        }
1464    }
1465
1466    if (my_data->csd != NULL) {
1467        ret = my_data->csd->start_record(ALL_SESSION_VSID, rec_mode);
1468        if (ret < 0) {
1469            ALOGE("%s: csd_client_start_record failed, error %d",
1470                  __func__, ret);
1471        }
1472    }
1473
1474    return ret;
1475}
1476
1477int platform_stop_incall_recording_usecase(void *platform)
1478{
1479    int ret = 0;
1480    struct platform_data *my_data = (struct platform_data *)platform;
1481
1482    if (my_data->csd != NULL) {
1483        ret = my_data->csd->stop_record(ALL_SESSION_VSID);
1484        if (ret < 0) {
1485            ALOGE("%s: csd_client_stop_record failed, error %d",
1486                  __func__, ret);
1487        }
1488    }
1489
1490    return ret;
1491}
1492
1493int platform_start_incall_music_usecase(void *platform)
1494{
1495    int ret = 0;
1496    struct platform_data *my_data = (struct platform_data *)platform;
1497
1498    if (my_data->csd != NULL) {
1499        ret = my_data->csd->start_playback(ALL_SESSION_VSID);
1500        if (ret < 0) {
1501            ALOGE("%s: csd_client_start_playback failed, error %d",
1502                  __func__, ret);
1503        }
1504    }
1505
1506    return ret;
1507}
1508
1509int platform_stop_incall_music_usecase(void *platform)
1510{
1511    int ret = 0;
1512    struct platform_data *my_data = (struct platform_data *)platform;
1513
1514    if (my_data->csd != NULL) {
1515        ret = my_data->csd->stop_playback(ALL_SESSION_VSID);
1516        if (ret < 0) {
1517            ALOGE("%s: csd_client_stop_playback failed, error %d",
1518                  __func__, ret);
1519        }
1520    }
1521
1522    return ret;
1523}
1524
1525/* Delay in Us */
1526int64_t platform_render_latency(audio_usecase_t usecase)
1527{
1528    switch (usecase) {
1529        case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER:
1530            return DEEP_BUFFER_PLATFORM_DELAY;
1531        case USECASE_AUDIO_PLAYBACK_LOW_LATENCY:
1532            return LOW_LATENCY_PLATFORM_DELAY;
1533        default:
1534            return 0;
1535    }
1536}
1537
1538int platform_set_snd_device_backend(snd_device_t device, const char *backend)
1539{
1540    int ret = 0;
1541
1542    if ((device < SND_DEVICE_MIN) || (device >= SND_DEVICE_MAX)) {
1543        ALOGE("%s: Invalid snd_device = %d",
1544            __func__, device);
1545        ret = -EINVAL;
1546        goto done;
1547    }
1548
1549    if (backend_table[device]) {
1550        free(backend_table[device]);
1551    }
1552    backend_table[device] = strdup(backend);
1553done:
1554    return ret;
1555}
1556
1557int platform_set_usecase_pcm_id(audio_usecase_t usecase, int32_t type, int32_t pcm_id)
1558{
1559    int ret = 0;
1560    if ((usecase <= USECASE_INVALID) || (usecase >= AUDIO_USECASE_MAX)) {
1561        ALOGE("%s: invalid usecase case idx %d", __func__, usecase);
1562        ret = -EINVAL;
1563        goto done;
1564    }
1565
1566    if ((type != 0) && (type != 1)) {
1567        ALOGE("%s: invalid usecase type", __func__);
1568        ret = -EINVAL;
1569    }
1570    pcm_device_table[usecase][type] = pcm_id;
1571done:
1572    return ret;
1573}
1574