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