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