platform.c revision cefbbac40220d4e7690d204eecff5f6ae3f63069
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        my_data->adev->mode == AUDIO_MODE_IN_CALL) {
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 ((mode == AUDIO_MODE_IN_CALL) ||
1190        (adev->enable_voicerx)) {
1191        if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
1192            devices & AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1193            devices & AUDIO_DEVICE_OUT_LINE) {
1194            if ((mode == AUDIO_MODE_IN_CALL) &&
1195                (adev->voice.tty_mode == TTY_MODE_FULL))
1196                snd_device = SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES;
1197            else if ((mode == AUDIO_MODE_IN_CALL) &&
1198                (adev->voice.tty_mode == TTY_MODE_VCO))
1199                snd_device = SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES;
1200            else if ((mode == AUDIO_MODE_IN_CALL) &&
1201                (adev->voice.tty_mode == TTY_MODE_HCO))
1202                snd_device = SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET;
1203            else {
1204                if (devices & AUDIO_DEVICE_OUT_LINE)
1205                    snd_device = SND_DEVICE_OUT_VOICE_LINE;
1206                else
1207                    snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES;
1208                }
1209        } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
1210            if (adev->bt_wb_speech_enabled) {
1211                snd_device = SND_DEVICE_OUT_BT_SCO_WB;
1212            } else {
1213                snd_device = SND_DEVICE_OUT_BT_SCO;
1214            }
1215        } else if (devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
1216            snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
1217        } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
1218            if(adev->voice.hac)
1219                snd_device = SND_DEVICE_OUT_VOICE_HAC_HANDSET;
1220            else if (is_operator_tmus())
1221                snd_device = SND_DEVICE_OUT_VOICE_HANDSET_TMUS;
1222            else
1223                snd_device = SND_DEVICE_OUT_VOICE_HANDSET;
1224        } else if (devices & AUDIO_DEVICE_OUT_TELEPHONY_TX)
1225            snd_device = SND_DEVICE_OUT_VOICE_TX;
1226
1227        if (snd_device != SND_DEVICE_NONE) {
1228            goto exit;
1229        }
1230    }
1231
1232    if (popcount(devices) == 2) {
1233        if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
1234                        AUDIO_DEVICE_OUT_SPEAKER)) {
1235            snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
1236        } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
1237                               AUDIO_DEVICE_OUT_SPEAKER)) {
1238            snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
1239        } else if (devices == (AUDIO_DEVICE_OUT_LINE |
1240                               AUDIO_DEVICE_OUT_SPEAKER)) {
1241            snd_device = SND_DEVICE_OUT_SPEAKER_AND_LINE;
1242        } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL |
1243                               AUDIO_DEVICE_OUT_SPEAKER)) {
1244            snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
1245        } else {
1246            ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
1247            goto exit;
1248        }
1249        if (snd_device != SND_DEVICE_NONE) {
1250            goto exit;
1251        }
1252    }
1253
1254    if (popcount(devices) != 1) {
1255        ALOGE("%s: Invalid output devices(%#x)", __func__, devices);
1256        goto exit;
1257    }
1258
1259    if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
1260        devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
1261        snd_device = SND_DEVICE_OUT_HEADPHONES;
1262    } else if (devices & AUDIO_DEVICE_OUT_LINE) {
1263        snd_device = SND_DEVICE_OUT_LINE;
1264    } else if (devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
1265        snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
1266    } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
1267        if (adev->speaker_lr_swap)
1268            snd_device = SND_DEVICE_OUT_SPEAKER_REVERSE;
1269        else
1270            snd_device = SND_DEVICE_OUT_SPEAKER;
1271    } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
1272        if (adev->bt_wb_speech_enabled) {
1273            snd_device = SND_DEVICE_OUT_BT_SCO_WB;
1274        } else {
1275            snd_device = SND_DEVICE_OUT_BT_SCO;
1276        }
1277    } else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1278        snd_device = SND_DEVICE_OUT_HDMI ;
1279    } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
1280        /*HAC support for voice-ish audio (eg visual voicemail)*/
1281        if(adev->voice.hac)
1282            snd_device = SND_DEVICE_OUT_VOICE_HAC_HANDSET;
1283        else
1284            snd_device = SND_DEVICE_OUT_HANDSET;
1285    } else {
1286        ALOGE("%s: Unknown device(s) %#x", __func__, devices);
1287    }
1288exit:
1289    ALOGV("%s: exit: snd_device(%s)", __func__, device_table[snd_device]);
1290    return snd_device;
1291}
1292
1293snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device)
1294{
1295    struct platform_data *my_data = (struct platform_data *)platform;
1296    struct audio_device *adev = my_data->adev;
1297    audio_source_t  source = (adev->active_input == NULL) ?
1298                                AUDIO_SOURCE_DEFAULT : adev->active_input->source;
1299
1300    audio_mode_t    mode   = adev->mode;
1301    audio_devices_t in_device = ((adev->active_input == NULL) ?
1302                                    AUDIO_DEVICE_NONE : adev->active_input->device)
1303                                & ~AUDIO_DEVICE_BIT_IN;
1304    audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
1305                                AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
1306    snd_device_t snd_device = SND_DEVICE_NONE;
1307    int channel_count = popcount(channel_mask);
1308
1309    ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
1310          __func__, out_device, in_device);
1311    if (mode == AUDIO_MODE_IN_CALL) {
1312        if (out_device == AUDIO_DEVICE_NONE) {
1313            ALOGE("%s: No output device set for voice call", __func__);
1314            goto exit;
1315        }
1316        if (adev->voice.tty_mode != TTY_MODE_OFF) {
1317            if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
1318                out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1319                out_device & AUDIO_DEVICE_OUT_LINE) {
1320                switch (adev->voice.tty_mode) {
1321                case TTY_MODE_FULL:
1322                    snd_device = SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC;
1323                    break;
1324                case TTY_MODE_VCO:
1325                    snd_device = SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC;
1326                    break;
1327                case TTY_MODE_HCO:
1328                    snd_device = SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC;
1329                    break;
1330                default:
1331                    ALOGE("%s: Invalid TTY mode (%#x)", __func__, adev->voice.tty_mode);
1332                }
1333                goto exit;
1334            }
1335        }
1336        if (out_device & AUDIO_DEVICE_OUT_EARPIECE) {
1337            if (my_data->fluence_in_voice_call == false) {
1338                snd_device = SND_DEVICE_IN_HANDSET_MIC;
1339            } else {
1340                if (is_operator_tmus())
1341                    snd_device = SND_DEVICE_IN_VOICE_DMIC_TMUS;
1342                else
1343                    snd_device = SND_DEVICE_IN_VOICE_DMIC;
1344            }
1345        } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
1346            snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
1347        } else if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
1348            if (adev->bt_wb_speech_enabled) {
1349                snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
1350            } else {
1351                snd_device = SND_DEVICE_IN_BT_SCO_MIC;
1352            }
1353        } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER ||
1354            out_device & AUDIO_DEVICE_OUT_SPEAKER_SAFE ||
1355            out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
1356            out_device & AUDIO_DEVICE_OUT_LINE) {
1357            if (my_data->fluence_in_voice_call && my_data->fluence_in_spkr_mode &&
1358                    my_data->dualmic_config != DUALMIC_CONFIG_NONE) {
1359                snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC;
1360            } else {
1361                snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
1362            }
1363        } else if (out_device & AUDIO_DEVICE_OUT_TELEPHONY_TX)
1364            snd_device = SND_DEVICE_IN_VOICE_RX;
1365    } else if (source == AUDIO_SOURCE_CAMCORDER) {
1366        if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
1367            in_device & AUDIO_DEVICE_IN_BACK_MIC) {
1368            snd_device = SND_DEVICE_IN_CAMCORDER_MIC;
1369        }
1370    } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) {
1371        if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
1372            if (my_data->dualmic_config != DUALMIC_CONFIG_NONE) {
1373                if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
1374                    snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_STEREO;
1375                else if (my_data->fluence_in_voice_rec &&
1376                         adev->active_input->enable_ns)
1377                    snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE;
1378            }
1379
1380            if (snd_device == SND_DEVICE_NONE) {
1381                if (adev->active_input->enable_ns)
1382                    snd_device = SND_DEVICE_IN_VOICE_REC_MIC_NS;
1383                else
1384                    snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
1385            }
1386        }
1387    } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1388        if (out_device & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))
1389            in_device = AUDIO_DEVICE_IN_BACK_MIC;
1390        if (adev->active_input) {
1391            if (adev->active_input->enable_aec &&
1392                    adev->active_input->enable_ns) {
1393                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
1394                    if (my_data->fluence_in_spkr_mode &&
1395                            my_data->fluence_in_voice_comm &&
1396                            my_data->dualmic_config != DUALMIC_CONFIG_NONE) {
1397                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
1398                    } else
1399                        snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
1400                } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
1401                    if (my_data->fluence_in_voice_comm &&
1402                            my_data->dualmic_config != DUALMIC_CONFIG_NONE) {
1403                        snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS;
1404                    } else
1405                        snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS;
1406                } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
1407                    snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
1408                }
1409                platform_set_echo_reference(adev, true, out_device);
1410            } else if (adev->active_input->enable_aec) {
1411                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
1412                    if (my_data->fluence_in_spkr_mode &&
1413                            my_data->fluence_in_voice_comm &&
1414                            my_data->dualmic_config != DUALMIC_CONFIG_NONE) {
1415                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC;
1416                    } else
1417                        snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
1418                } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
1419                    if (my_data->fluence_in_voice_comm &&
1420                            my_data->dualmic_config != DUALMIC_CONFIG_NONE) {
1421                        snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC;
1422                    } else
1423                        snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
1424               } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
1425                   snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
1426               }
1427                platform_set_echo_reference(adev, true, out_device);
1428            } else if (adev->active_input->enable_ns) {
1429                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
1430                    if (my_data->fluence_in_spkr_mode &&
1431                            my_data->fluence_in_voice_comm &&
1432                            my_data->dualmic_config != DUALMIC_CONFIG_NONE) {
1433                        snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS;
1434                    } else
1435                        snd_device = SND_DEVICE_IN_SPEAKER_MIC_NS;
1436                } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
1437                    if (my_data->fluence_in_voice_comm &&
1438                            my_data->dualmic_config != DUALMIC_CONFIG_NONE) {
1439                        snd_device = SND_DEVICE_IN_HANDSET_DMIC_NS;
1440                    } else
1441                        snd_device = SND_DEVICE_IN_HANDSET_MIC_NS;
1442                }
1443            }
1444        }
1445    } else if (source == AUDIO_SOURCE_DEFAULT) {
1446        goto exit;
1447    }
1448
1449
1450    if (snd_device != SND_DEVICE_NONE) {
1451        goto exit;
1452    }
1453
1454    if (in_device != AUDIO_DEVICE_NONE &&
1455            !(in_device & AUDIO_DEVICE_IN_VOICE_CALL) &&
1456            !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) {
1457        if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
1458            if (my_data->dualmic_config != DUALMIC_CONFIG_NONE &&
1459                    channel_count == 2)
1460                snd_device = SND_DEVICE_IN_HANDSET_DMIC_STEREO;
1461            else
1462                snd_device = SND_DEVICE_IN_HANDSET_MIC;
1463        } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
1464            if (my_data->dualmic_config != DUALMIC_CONFIG_NONE &&
1465                    channel_count == 2)
1466                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_STEREO;
1467            else
1468                snd_device = SND_DEVICE_IN_SPEAKER_MIC;
1469        } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
1470            snd_device = SND_DEVICE_IN_HEADSET_MIC;
1471        } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
1472            if (adev->bt_wb_speech_enabled) {
1473                snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
1474            } else {
1475                snd_device = SND_DEVICE_IN_BT_SCO_MIC;
1476            }
1477        } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) {
1478            snd_device = SND_DEVICE_IN_HDMI_MIC;
1479        } else {
1480            ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
1481            ALOGW("%s: Using default handset-mic", __func__);
1482            snd_device = SND_DEVICE_IN_HANDSET_MIC;
1483        }
1484    } else {
1485        if (out_device & AUDIO_DEVICE_OUT_EARPIECE) {
1486            snd_device = SND_DEVICE_IN_HANDSET_MIC;
1487        } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
1488            snd_device = SND_DEVICE_IN_HEADSET_MIC;
1489        } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER ||
1490                   out_device & AUDIO_DEVICE_OUT_SPEAKER_SAFE ||
1491                   out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
1492                   out_device & AUDIO_DEVICE_OUT_LINE) {
1493            if (channel_count == 2)
1494                snd_device = SND_DEVICE_IN_SPEAKER_DMIC_STEREO;
1495            else
1496                snd_device = SND_DEVICE_IN_SPEAKER_MIC;
1497        } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
1498            if (adev->bt_wb_speech_enabled) {
1499                snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
1500            } else {
1501                snd_device = SND_DEVICE_IN_BT_SCO_MIC;
1502            }
1503        } else if (out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1504            snd_device = SND_DEVICE_IN_HDMI_MIC;
1505        } else {
1506            ALOGE("%s: Unknown output device(s) %#x", __func__, out_device);
1507            ALOGW("%s: Using default handset-mic", __func__);
1508            snd_device = SND_DEVICE_IN_HANDSET_MIC;
1509        }
1510    }
1511exit:
1512    ALOGV("%s: exit: in_snd_device(%s)", __func__, device_table[snd_device]);
1513    return snd_device;
1514}
1515
1516int platform_set_hdmi_channels(void *platform,  int channel_count)
1517{
1518    struct platform_data *my_data = (struct platform_data *)platform;
1519    struct audio_device *adev = my_data->adev;
1520    struct mixer_ctl *ctl;
1521    const char *channel_cnt_str = NULL;
1522    const char *mixer_ctl_name = "HDMI_RX Channels";
1523    switch (channel_count) {
1524    case 8:
1525        channel_cnt_str = "Eight"; break;
1526    case 7:
1527        channel_cnt_str = "Seven"; break;
1528    case 6:
1529        channel_cnt_str = "Six"; break;
1530    case 5:
1531        channel_cnt_str = "Five"; break;
1532    case 4:
1533        channel_cnt_str = "Four"; break;
1534    case 3:
1535        channel_cnt_str = "Three"; break;
1536    default:
1537        channel_cnt_str = "Two"; break;
1538    }
1539    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1540    if (!ctl) {
1541        ALOGE("%s: Could not get ctl for mixer cmd - %s",
1542              __func__, mixer_ctl_name);
1543        return -EINVAL;
1544    }
1545    ALOGV("HDMI channel count: %s", channel_cnt_str);
1546    mixer_ctl_set_enum_by_string(ctl, channel_cnt_str);
1547    return 0;
1548}
1549
1550int platform_edid_get_max_channels(void *platform)
1551{
1552    struct platform_data *my_data = (struct platform_data *)platform;
1553    struct audio_device *adev = my_data->adev;
1554    char block[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE];
1555    char *sad = block;
1556    int num_audio_blocks;
1557    int channel_count;
1558    int max_channels = 0;
1559    int i, ret, count;
1560
1561    struct mixer_ctl *ctl;
1562
1563    ctl = mixer_get_ctl_by_name(adev->mixer, AUDIO_DATA_BLOCK_MIXER_CTL);
1564    if (!ctl) {
1565        ALOGE("%s: Could not get ctl for mixer cmd - %s",
1566              __func__, AUDIO_DATA_BLOCK_MIXER_CTL);
1567        return 0;
1568    }
1569
1570    mixer_ctl_update(ctl);
1571
1572    count = mixer_ctl_get_num_values(ctl);
1573
1574    /* Read SAD blocks, clamping the maximum size for safety */
1575    if (count > (int)sizeof(block))
1576        count = (int)sizeof(block);
1577
1578    ret = mixer_ctl_get_array(ctl, block, count);
1579    if (ret != 0) {
1580        ALOGE("%s: mixer_ctl_get_array() failed to get EDID info", __func__);
1581        return 0;
1582    }
1583
1584    /* Calculate the number of SAD blocks */
1585    num_audio_blocks = count / SAD_BLOCK_SIZE;
1586
1587    for (i = 0; i < num_audio_blocks; i++) {
1588        /* Only consider LPCM blocks */
1589        if ((sad[0] >> 3) != EDID_FORMAT_LPCM) {
1590            sad += 3;
1591            continue;
1592        }
1593
1594        channel_count = (sad[0] & 0x7) + 1;
1595        if (channel_count > max_channels)
1596            max_channels = channel_count;
1597
1598        /* Advance to next block */
1599        sad += 3;
1600    }
1601
1602    return max_channels;
1603}
1604
1605int platform_set_incall_recording_session_id(void *platform,
1606                                             uint32_t session_id, int rec_mode)
1607{
1608    int ret = 0;
1609    struct platform_data *my_data = (struct platform_data *)platform;
1610    struct audio_device *adev = my_data->adev;
1611    struct mixer_ctl *ctl;
1612    const char *mixer_ctl_name = "Voc VSID";
1613    int num_ctl_values;
1614    int i;
1615
1616    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1617    if (!ctl) {
1618        ALOGE("%s: Could not get ctl for mixer cmd - %s",
1619              __func__, mixer_ctl_name);
1620        ret = -EINVAL;
1621    } else {
1622        num_ctl_values = mixer_ctl_get_num_values(ctl);
1623        for (i = 0; i < num_ctl_values; i++) {
1624            if (mixer_ctl_set_value(ctl, i, session_id)) {
1625                ALOGV("Error: invalid session_id: %x", session_id);
1626                ret = -EINVAL;
1627                break;
1628            }
1629        }
1630    }
1631
1632    if (my_data->csd != NULL) {
1633        ret = my_data->csd->start_record(ALL_SESSION_VSID, rec_mode);
1634        if (ret < 0) {
1635            ALOGE("%s: csd_client_start_record failed, error %d",
1636                  __func__, ret);
1637        }
1638    }
1639
1640    return ret;
1641}
1642
1643int platform_stop_incall_recording_usecase(void *platform)
1644{
1645    int ret = 0;
1646    struct platform_data *my_data = (struct platform_data *)platform;
1647
1648    if (my_data->csd != NULL) {
1649        ret = my_data->csd->stop_record(ALL_SESSION_VSID);
1650        if (ret < 0) {
1651            ALOGE("%s: csd_client_stop_record failed, error %d",
1652                  __func__, ret);
1653        }
1654    }
1655
1656    return ret;
1657}
1658
1659int platform_start_incall_music_usecase(void *platform)
1660{
1661    int ret = 0;
1662    struct platform_data *my_data = (struct platform_data *)platform;
1663
1664    if (my_data->csd != NULL) {
1665        ret = my_data->csd->start_playback(ALL_SESSION_VSID);
1666        if (ret < 0) {
1667            ALOGE("%s: csd_client_start_playback failed, error %d",
1668                  __func__, ret);
1669        }
1670    }
1671
1672    return ret;
1673}
1674
1675int platform_stop_incall_music_usecase(void *platform)
1676{
1677    int ret = 0;
1678    struct platform_data *my_data = (struct platform_data *)platform;
1679
1680    if (my_data->csd != NULL) {
1681        ret = my_data->csd->stop_playback(ALL_SESSION_VSID);
1682        if (ret < 0) {
1683            ALOGE("%s: csd_client_stop_playback failed, error %d",
1684                  __func__, ret);
1685        }
1686    }
1687
1688    return ret;
1689}
1690
1691/* Delay in Us */
1692int64_t platform_render_latency(audio_usecase_t usecase)
1693{
1694    switch (usecase) {
1695        case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER:
1696            return DEEP_BUFFER_PLATFORM_DELAY;
1697        case USECASE_AUDIO_PLAYBACK_LOW_LATENCY:
1698            return LOW_LATENCY_PLATFORM_DELAY;
1699        default:
1700            return 0;
1701    }
1702}
1703
1704int platform_set_snd_device_backend(snd_device_t device, const char *backend)
1705{
1706    int ret = 0;
1707
1708    if ((device < SND_DEVICE_MIN) || (device >= SND_DEVICE_MAX)) {
1709        ALOGE("%s: Invalid snd_device = %d",
1710            __func__, device);
1711        ret = -EINVAL;
1712        goto done;
1713    }
1714
1715    if (backend_table[device]) {
1716        free(backend_table[device]);
1717    }
1718    backend_table[device] = strdup(backend);
1719done:
1720    return ret;
1721}
1722
1723int platform_set_usecase_pcm_id(audio_usecase_t usecase, int32_t type, int32_t pcm_id)
1724{
1725    int ret = 0;
1726    if ((usecase <= USECASE_INVALID) || (usecase >= AUDIO_USECASE_MAX)) {
1727        ALOGE("%s: invalid usecase case idx %d", __func__, usecase);
1728        ret = -EINVAL;
1729        goto done;
1730    }
1731
1732    if ((type != 0) && (type != 1)) {
1733        ALOGE("%s: invalid usecase type", __func__);
1734        ret = -EINVAL;
1735    }
1736    pcm_device_table[usecase][type] = pcm_id;
1737done:
1738    return ret;
1739}
1740