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