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