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