blob: a6f2a8c1b64f2289755c1f9d4efe49dfd8e388f4 [file] [log] [blame]
Eric Laurentb23d5282013-05-14 15:27:20 -07001/*
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002 * Copyright (C) 2013-2014 The Android Open Source Project
Eric Laurentb23d5282013-05-14 15:27:20 -07003 *
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>
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -070024#include <cutils/str_parms.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070025#include <cutils/properties.h>
26#include <audio_hw.h>
27#include <platform_api.h>
28#include "platform.h"
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -070029#ifdef PLATFORM_MSM8084
30#include "mdm_detect.h"
31#endif
Eric Laurentb23d5282013-05-14 15:27:20 -070032
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -070033#define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
Eric Laurentb23d5282013-05-14 15:27:20 -070034#define LIB_ACDB_LOADER "libacdbloader.so"
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -070035#define AUDIO_DATA_BLOCK_MIXER_CTL "HDMI EDID"
Eric Laurentb23d5282013-05-14 15:27:20 -070036
37#define DUALMIC_CONFIG_NONE 0 /* Target does not contain 2 mics */
38#define DUALMIC_CONFIG_ENDFIRE 1
39#define DUALMIC_CONFIG_BROADSIDE 2
40
41/*
Eric Laurentb23d5282013-05-14 15:27:20 -070042 * This file will have a maximum of 38 bytes:
43 *
44 * 4 bytes: number of audio blocks
45 * 4 bytes: total length of Short Audio Descriptor (SAD) blocks
46 * Maximum 10 * 3 bytes: SAD blocks
47 */
48#define MAX_SAD_BLOCKS 10
49#define SAD_BLOCK_SIZE 3
50
51/* EDID format ID for LPCM audio */
52#define EDID_FORMAT_LPCM 1
53
sangwoo1b9f4b32013-06-21 18:22:55 -070054/* Retry for delay in FW loading*/
55#define RETRY_NUMBER 10
56#define RETRY_US 500000
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070057#define MAX_SND_CARD 8
sangwoo53b2cf02013-07-25 19:18:44 -070058
Eric Laurentb23d5282013-05-14 15:27:20 -070059struct audio_block_header
60{
61 int reserved;
62 int length;
63};
64
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -070065/* Audio calibration related functions */
Eric Laurentb23d5282013-05-14 15:27:20 -070066typedef void (*acdb_deallocate_t)();
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -070067#ifdef PLATFORM_MSM8084
68typedef int (*acdb_init_t)(char *);
69#else
Eric Laurentb23d5282013-05-14 15:27:20 -070070typedef int (*acdb_init_t)();
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -070071#endif
Eric Laurentb23d5282013-05-14 15:27:20 -070072typedef void (*acdb_send_audio_cal_t)(int, int);
73typedef void (*acdb_send_voice_cal_t)(int, int);
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -070074typedef int (*acdb_reload_vocvoltable_t)(int);
Eric Laurentb23d5282013-05-14 15:27:20 -070075
76/* Audio calibration related functions */
77struct platform_data {
78 struct audio_device *adev;
79 bool fluence_in_spkr_mode;
80 bool fluence_in_voice_call;
81 bool fluence_in_voice_rec;
82 int dualmic_config;
Eric Laurentb23d5282013-05-14 15:27:20 -070083 void *acdb_handle;
84 acdb_init_t acdb_init;
85 acdb_deallocate_t acdb_deallocate;
86 acdb_send_audio_cal_t acdb_send_audio_cal;
87 acdb_send_voice_cal_t acdb_send_voice_cal;
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -070088 acdb_reload_vocvoltable_t acdb_reload_vocvoltable;
89 struct csd_data *csd;
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -050090 bool ext_speaker;
91 bool ext_earpiece;
Eric Laurentb23d5282013-05-14 15:27:20 -070092};
93
Haynes Mathew George98c95622014-06-20 19:14:25 -070094static int pcm_device_table[AUDIO_USECASE_MAX][2] = {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -070095 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {DEEP_BUFFER_PCM_DEVICE,
96 DEEP_BUFFER_PCM_DEVICE},
97 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
98 LOWLATENCY_PCM_DEVICE},
99 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {MULTIMEDIA2_PCM_DEVICE,
100 MULTIMEDIA2_PCM_DEVICE},
101 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {PLAYBACK_OFFLOAD_DEVICE,
102 PLAYBACK_OFFLOAD_DEVICE},
103 [USECASE_AUDIO_RECORD] = {AUDIO_RECORD_PCM_DEVICE,
104 AUDIO_RECORD_PCM_DEVICE},
105 [USECASE_AUDIO_RECORD_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
106 LOWLATENCY_PCM_DEVICE},
107 [USECASE_VOICE_CALL] = {VOICE_CALL_PCM_DEVICE,
108 VOICE_CALL_PCM_DEVICE},
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700109 [USECASE_VOICE2_CALL] = {VOICE2_CALL_PCM_DEVICE, VOICE2_CALL_PCM_DEVICE},
110 [USECASE_VOLTE_CALL] = {VOLTE_CALL_PCM_DEVICE, VOLTE_CALL_PCM_DEVICE},
111 [USECASE_QCHAT_CALL] = {QCHAT_CALL_PCM_DEVICE, QCHAT_CALL_PCM_DEVICE},
112 [USECASE_VOWLAN_CALL] = {VOWLAN_CALL_PCM_DEVICE, VOWLAN_CALL_PCM_DEVICE},
113 [USECASE_INCALL_REC_UPLINK] = {AUDIO_RECORD_PCM_DEVICE,
114 AUDIO_RECORD_PCM_DEVICE},
115 [USECASE_INCALL_REC_DOWNLINK] = {AUDIO_RECORD_PCM_DEVICE,
116 AUDIO_RECORD_PCM_DEVICE},
117 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = {AUDIO_RECORD_PCM_DEVICE,
118 AUDIO_RECORD_PCM_DEVICE},
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800119 [USECASE_AUDIO_HFP_SCO] = {HFP_PCM_RX, HFP_SCO_RX},
Eric Laurentb23d5282013-05-14 15:27:20 -0700120};
121
122/* Array to store sound devices */
123static const char * const device_table[SND_DEVICE_MAX] = {
124 [SND_DEVICE_NONE] = "none",
125 /* Playback sound devices */
126 [SND_DEVICE_OUT_HANDSET] = "handset",
127 [SND_DEVICE_OUT_SPEAKER] = "speaker",
128 [SND_DEVICE_OUT_SPEAKER_REVERSE] = "speaker-reverse",
129 [SND_DEVICE_OUT_HEADPHONES] = "headphones",
130 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones",
131 [SND_DEVICE_OUT_VOICE_HANDSET] = "voice-handset",
Eric Laurent9d0d3f12014-07-25 12:40:29 -0500132 [SND_DEVICE_OUT_VOICE_HAC_HANDSET] = "voice-hac-handset",
Eric Laurentb23d5282013-05-14 15:27:20 -0700133 [SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker",
134 [SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones",
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",
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -0700138 [SND_DEVICE_OUT_BT_SCO_WB] = "bt-sco-headset-wb",
Eric Laurentb23d5282013-05-14 15:27:20 -0700139 [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_SPEAKER_MIC] = "speaker-mic",
147 [SND_DEVICE_IN_HEADSET_MIC] = "headset-mic",
148 [SND_DEVICE_IN_HANDSET_MIC_AEC] = "handset-mic",
Eric Laurent34fa7692014-03-07 09:31:06 -0800149 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = "speaker-mic-aec",
Eric Laurentb23d5282013-05-14 15:27:20 -0700150 [SND_DEVICE_IN_HEADSET_MIC_AEC] = "headset-mic",
151 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "voice-speaker-mic",
152 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "voice-headset-mic",
153 [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic",
154 [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic",
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -0700155 [SND_DEVICE_IN_BT_SCO_MIC_WB] = "bt-sco-mic-wb",
Eric Laurentb23d5282013-05-14 15:27:20 -0700156 [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic",
157 [SND_DEVICE_IN_VOICE_DMIC_EF] = "voice-dmic-ef",
158 [SND_DEVICE_IN_VOICE_DMIC_BS] = "voice-dmic-bs",
159 [SND_DEVICE_IN_VOICE_DMIC_EF_TMUS] = "voice-dmic-ef-tmus",
160 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF] = "voice-speaker-dmic-ef",
161 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS] = "voice-speaker-dmic-bs",
162 [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = "voice-tty-full-headset-mic",
163 [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = "voice-tty-vco-handset-mic",
164 [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = "voice-tty-hco-headset-mic",
165 [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic",
166 [SND_DEVICE_IN_VOICE_REC_DMIC_EF] = "voice-rec-dmic-ef",
167 [SND_DEVICE_IN_VOICE_REC_DMIC_BS] = "voice-rec-dmic-bs",
168 [SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE] = "voice-rec-dmic-ef-fluence",
169 [SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE] = "voice-rec-dmic-bs-fluence",
170};
171
172/* ACDB IDs (audio DSP path configuration IDs) for each sound device */
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700173static int acdb_device_table[SND_DEVICE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700174 [SND_DEVICE_NONE] = -1,
175 [SND_DEVICE_OUT_HANDSET] = 7,
176 [SND_DEVICE_OUT_SPEAKER] = 15,
177 [SND_DEVICE_OUT_SPEAKER_REVERSE] = 15,
178 [SND_DEVICE_OUT_HEADPHONES] = 10,
179 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = 10,
Ravi Kumar Alamanda1de6e5a2014-06-19 21:55:39 -0500180#ifdef PLATFORM_MSM8084
181 [SND_DEVICE_OUT_VOICE_HANDSET] = 67,
182 [SND_DEVICE_OUT_VOICE_SPEAKER] = 66,
183#else
Eric Laurentb23d5282013-05-14 15:27:20 -0700184 [SND_DEVICE_OUT_VOICE_HANDSET] = 7,
185 [SND_DEVICE_OUT_VOICE_SPEAKER] = 15,
Ravi Kumar Alamanda1de6e5a2014-06-19 21:55:39 -0500186#endif
Eric Laurent9d0d3f12014-07-25 12:40:29 -0500187 [SND_DEVICE_OUT_VOICE_HAC_HANDSET] = 53,
Eric Laurentb23d5282013-05-14 15:27:20 -0700188 [SND_DEVICE_OUT_VOICE_HEADPHONES] = 10,
189 [SND_DEVICE_OUT_HDMI] = 18,
190 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 15,
191 [SND_DEVICE_OUT_BT_SCO] = 22,
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -0700192 [SND_DEVICE_OUT_BT_SCO_WB] = 39,
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700193 [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = ACDB_ID_VOICE_HANDSET_TMUS,
Eric Laurentb23d5282013-05-14 15:27:20 -0700194 [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = 17,
195 [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = 17,
196 [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = 37,
197
198 [SND_DEVICE_IN_HANDSET_MIC] = 4,
199 [SND_DEVICE_IN_SPEAKER_MIC] = 4, /* ToDo: Check if this needs to changed to 11 */
200 [SND_DEVICE_IN_HEADSET_MIC] = 8,
201 [SND_DEVICE_IN_HANDSET_MIC_AEC] = 40,
202 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = 42,
203 [SND_DEVICE_IN_HEADSET_MIC_AEC] = 47,
204 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = 11,
205 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = 8,
206 [SND_DEVICE_IN_HDMI_MIC] = 4,
207 [SND_DEVICE_IN_BT_SCO_MIC] = 21,
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -0700208 [SND_DEVICE_IN_BT_SCO_MIC_WB] = 38,
Eric Laurentb23d5282013-05-14 15:27:20 -0700209 [SND_DEVICE_IN_CAMCORDER_MIC] = 61,
210 [SND_DEVICE_IN_VOICE_DMIC_EF] = 41,
211 [SND_DEVICE_IN_VOICE_DMIC_BS] = 5,
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700212 [SND_DEVICE_IN_VOICE_DMIC_EF_TMUS] = ACDB_ID_VOICE_DMIC_EF_TMUS,
Eric Laurentb23d5282013-05-14 15:27:20 -0700213 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF] = 43,
214 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS] = 12,
215 [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = 16,
216 [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = 36,
217 [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = 16,
218 [SND_DEVICE_IN_VOICE_REC_MIC] = 62,
219 /* TODO: Update with proper acdb ids */
220 [SND_DEVICE_IN_VOICE_REC_DMIC_EF] = 62,
221 [SND_DEVICE_IN_VOICE_REC_DMIC_BS] = 62,
222 [SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE] = 6,
223 [SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE] = 5,
224};
225
Haynes Mathew George98c95622014-06-20 19:14:25 -0700226struct name_to_index {
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700227 char name[100];
228 unsigned int index;
229};
230
231#define TO_NAME_INDEX(X) #X, X
232
Haynes Mathew George98c95622014-06-20 19:14:25 -0700233/* Used to get index from parsed string */
234static const struct name_to_index snd_device_name_index[SND_DEVICE_MAX] = {
235 /* out */
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700236 {TO_NAME_INDEX(SND_DEVICE_OUT_HANDSET)},
237 {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER)},
238 {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_REVERSE)},
239 {TO_NAME_INDEX(SND_DEVICE_OUT_HEADPHONES)},
240 {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES)},
241 {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HANDSET)},
242 {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER)},
243 {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HEADPHONES)},
244 {TO_NAME_INDEX(SND_DEVICE_OUT_HDMI)},
245 {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_HDMI)},
246 {TO_NAME_INDEX(SND_DEVICE_OUT_BT_SCO)},
247 {TO_NAME_INDEX(SND_DEVICE_OUT_BT_SCO_WB)},
Haynes Mathew George98c95622014-06-20 19:14:25 -0700248 {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HANDSET_TMUS)},
Eric Laurent9d0d3f12014-07-25 12:40:29 -0500249 {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HAC_HANDSET)},
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700250 {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES)},
251 {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES)},
252 {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET)},
Haynes Mathew George98c95622014-06-20 19:14:25 -0700253
254 /* in */
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700255 {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC)},
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700256 {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_MIC)},
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700257 {TO_NAME_INDEX(SND_DEVICE_IN_HEADSET_MIC)},
Haynes Mathew George98c95622014-06-20 19:14:25 -0700258 {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC_AEC)},
259 {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_MIC_AEC)},
260 {TO_NAME_INDEX(SND_DEVICE_IN_HEADSET_MIC_AEC)},
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700261 {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_SPEAKER_MIC)},
262 {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_HEADSET_MIC)},
263 {TO_NAME_INDEX(SND_DEVICE_IN_HDMI_MIC)},
264 {TO_NAME_INDEX(SND_DEVICE_IN_BT_SCO_MIC)},
265 {TO_NAME_INDEX(SND_DEVICE_IN_BT_SCO_MIC_WB)},
266 {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_MIC)},
Haynes Mathew George98c95622014-06-20 19:14:25 -0700267 {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_DMIC_EF)},
268 {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_DMIC_BS)},
269 {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_DMIC_EF_TMUS)},
270 {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF)},
271 {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS)},
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700272 {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC)},
273 {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC)},
274 {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC)},
275 {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_REC_MIC)},
Haynes Mathew George98c95622014-06-20 19:14:25 -0700276 {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_REC_DMIC_EF)},
277 {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_REC_DMIC_BS)},
278 {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE)},
279 {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE)},
280};
281
282static char * backend_table[SND_DEVICE_MAX] = {0};
283
284static const struct name_to_index usecase_name_index[AUDIO_USECASE_MAX] = {
285 {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_DEEP_BUFFER)},
286 {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_LOW_LATENCY)},
287 {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_MULTI_CH)},
288 {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD)},
289 {TO_NAME_INDEX(USECASE_AUDIO_RECORD)},
290 {TO_NAME_INDEX(USECASE_AUDIO_RECORD_LOW_LATENCY)},
291 {TO_NAME_INDEX(USECASE_VOICE_CALL)},
292 {TO_NAME_INDEX(USECASE_VOICE2_CALL)},
293 {TO_NAME_INDEX(USECASE_VOLTE_CALL)},
294 {TO_NAME_INDEX(USECASE_QCHAT_CALL)},
295 {TO_NAME_INDEX(USECASE_VOWLAN_CALL)},
296 {TO_NAME_INDEX(USECASE_INCALL_REC_UPLINK)},
297 {TO_NAME_INDEX(USECASE_INCALL_REC_DOWNLINK)},
298 {TO_NAME_INDEX(USECASE_INCALL_REC_UPLINK_AND_DOWNLINK)},
299 {TO_NAME_INDEX(USECASE_AUDIO_HFP_SCO)},
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700300};
301
Haynes Mathew George7ff216f2013-09-11 19:51:41 -0700302#define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL)
303#define LOW_LATENCY_PLATFORM_DELAY (13*1000LL)
304
Eric Laurentb23d5282013-05-14 15:27:20 -0700305static pthread_once_t check_op_once_ctl = PTHREAD_ONCE_INIT;
306static bool is_tmus = false;
307
308static void check_operator()
309{
310 char value[PROPERTY_VALUE_MAX];
311 int mccmnc;
312 property_get("gsm.sim.operator.numeric",value,"0");
313 mccmnc = atoi(value);
314 ALOGD("%s: tmus mccmnc %d", __func__, mccmnc);
315 switch(mccmnc) {
316 /* TMUS MCC(310), MNC(490, 260, 026) */
317 case 310490:
318 case 310260:
319 case 310026:
sangwon.jeonb891db52013-09-14 17:39:15 +0900320 /* Add new TMUS MNC(800, 660, 580, 310, 270, 250, 240, 230, 220, 210, 200, 160) */
321 case 310800:
322 case 310660:
323 case 310580:
324 case 310310:
325 case 310270:
326 case 310250:
327 case 310240:
328 case 310230:
329 case 310220:
330 case 310210:
331 case 310200:
332 case 310160:
Eric Laurentb23d5282013-05-14 15:27:20 -0700333 is_tmus = true;
334 break;
335 }
336}
337
338bool is_operator_tmus()
339{
340 pthread_once(&check_op_once_ctl, check_operator);
341 return is_tmus;
342}
343
344static int set_echo_reference(struct mixer *mixer, const char* ec_ref)
345{
346 struct mixer_ctl *ctl;
347 const char *mixer_ctl_name = "EC_REF_RX";
348
349 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
350 if (!ctl) {
351 ALOGE("%s: Could not get ctl for mixer cmd - %s",
352 __func__, mixer_ctl_name);
353 return -EINVAL;
354 }
355 ALOGV("Setting EC Reference: %s", ec_ref);
356 mixer_ctl_set_enum_by_string(ctl, ec_ref);
357 return 0;
358}
359
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700360static struct csd_data *open_csd_client(bool i2s_ext_modem)
361{
362 struct csd_data *csd = calloc(1, sizeof(struct csd_data));
363
364 csd->csd_client = dlopen(LIB_CSD_CLIENT, RTLD_NOW);
365 if (csd->csd_client == NULL) {
366 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_CSD_CLIENT);
367 goto error;
368 } else {
369 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_CSD_CLIENT);
370
371 csd->deinit = (deinit_t)dlsym(csd->csd_client,
372 "csd_client_deinit");
373 if (csd->deinit == NULL) {
374 ALOGE("%s: dlsym error %s for csd_client_deinit", __func__,
375 dlerror());
376 goto error;
377 }
378 csd->disable_device = (disable_device_t)dlsym(csd->csd_client,
379 "csd_client_disable_device");
380 if (csd->disable_device == NULL) {
381 ALOGE("%s: dlsym error %s for csd_client_disable_device",
382 __func__, dlerror());
383 goto error;
384 }
385 csd->enable_device_config = (enable_device_config_t)dlsym(csd->csd_client,
386 "csd_client_enable_device_config");
387 if (csd->enable_device_config == NULL) {
388 ALOGE("%s: dlsym error %s for csd_client_enable_device_config",
389 __func__, dlerror());
390 goto error;
391 }
392 csd->enable_device = (enable_device_t)dlsym(csd->csd_client,
393 "csd_client_enable_device");
394 if (csd->enable_device == NULL) {
395 ALOGE("%s: dlsym error %s for csd_client_enable_device",
396 __func__, dlerror());
397 goto error;
398 }
399 csd->start_voice = (start_voice_t)dlsym(csd->csd_client,
400 "csd_client_start_voice");
401 if (csd->start_voice == NULL) {
402 ALOGE("%s: dlsym error %s for csd_client_start_voice",
403 __func__, dlerror());
404 goto error;
405 }
406 csd->stop_voice = (stop_voice_t)dlsym(csd->csd_client,
407 "csd_client_stop_voice");
408 if (csd->stop_voice == NULL) {
409 ALOGE("%s: dlsym error %s for csd_client_stop_voice",
410 __func__, dlerror());
411 goto error;
412 }
413 csd->volume = (volume_t)dlsym(csd->csd_client,
414 "csd_client_volume");
415 if (csd->volume == NULL) {
416 ALOGE("%s: dlsym error %s for csd_client_volume",
417 __func__, dlerror());
418 goto error;
419 }
420 csd->mic_mute = (mic_mute_t)dlsym(csd->csd_client,
421 "csd_client_mic_mute");
422 if (csd->mic_mute == NULL) {
423 ALOGE("%s: dlsym error %s for csd_client_mic_mute",
424 __func__, dlerror());
425 goto error;
426 }
427 csd->slow_talk = (slow_talk_t)dlsym(csd->csd_client,
428 "csd_client_slow_talk");
429 if (csd->slow_talk == NULL) {
430 ALOGE("%s: dlsym error %s for csd_client_slow_talk",
431 __func__, dlerror());
432 goto error;
433 }
434 csd->start_playback = (start_playback_t)dlsym(csd->csd_client,
435 "csd_client_start_playback");
436 if (csd->start_playback == NULL) {
437 ALOGE("%s: dlsym error %s for csd_client_start_playback",
438 __func__, dlerror());
439 goto error;
440 }
441 csd->stop_playback = (stop_playback_t)dlsym(csd->csd_client,
442 "csd_client_stop_playback");
443 if (csd->stop_playback == NULL) {
444 ALOGE("%s: dlsym error %s for csd_client_stop_playback",
445 __func__, dlerror());
446 goto error;
447 }
448 csd->start_record = (start_record_t)dlsym(csd->csd_client,
449 "csd_client_start_record");
450 if (csd->start_record == NULL) {
451 ALOGE("%s: dlsym error %s for csd_client_start_record",
452 __func__, dlerror());
453 goto error;
454 }
455 csd->stop_record = (stop_record_t)dlsym(csd->csd_client,
456 "csd_client_stop_record");
457 if (csd->stop_record == NULL) {
458 ALOGE("%s: dlsym error %s for csd_client_stop_record",
459 __func__, dlerror());
460 goto error;
461 }
462
463 csd->get_sample_rate = (get_sample_rate_t)dlsym(csd->csd_client,
464 "csd_client_get_sample_rate");
465 if (csd->get_sample_rate == NULL) {
466 ALOGE("%s: dlsym error %s for csd_client_get_sample_rate",
467 __func__, dlerror());
468
469 goto error;
470 }
471
472 csd->init = (init_t)dlsym(csd->csd_client, "csd_client_init");
473
474 if (csd->init == NULL) {
475 ALOGE("%s: dlsym error %s for csd_client_init",
476 __func__, dlerror());
477 goto error;
478 } else {
479 csd->init(i2s_ext_modem);
480 }
481 }
482 return csd;
483
484error:
485 free(csd);
486 csd = NULL;
487 return csd;
488}
489
490void close_csd_client(struct csd_data *csd)
491{
492 if (csd != NULL) {
493 csd->deinit();
494 dlclose(csd->csd_client);
495 free(csd);
496 csd = NULL;
497 }
498}
499
500static void platform_csd_init(struct platform_data *my_data)
501{
502#ifdef PLATFORM_MSM8084
503 struct dev_info mdm_detect_info;
504 int ret = 0;
505
506 /* Call ESOC API to get the number of modems.
507 * If the number of modems is not zero, load CSD Client specific
508 * symbols. Voice call is handled by MDM and apps processor talks to
509 * MDM through CSD Client
510 */
511 ret = get_system_info(&mdm_detect_info);
512 if (ret > 0) {
513 ALOGE("%s: Failed to get system info, ret %d", __func__, ret);
514 }
515 ALOGD("%s: num_modems %d\n", __func__, mdm_detect_info.num_modems);
516
517 if (mdm_detect_info.num_modems > 0)
518 my_data->csd = open_csd_client(false /*is_i2s_ext_modem*/);
519#else
520 my_data->csd = NULL;
521#endif
522}
523
Haynes Mathew George98c95622014-06-20 19:14:25 -0700524static void set_platform_defaults(struct platform_data * my_data)
525{
526 int32_t dev;
527 for (dev = 0; dev < SND_DEVICE_MAX; dev++) {
528 backend_table[dev] = NULL;
529 }
530
531 // TBD - do these go to the platform-info.xml file.
532 // will help in avoiding strdups here
533 backend_table[SND_DEVICE_IN_BT_SCO_MIC] = strdup("bt-sco");
534 backend_table[SND_DEVICE_OUT_BT_SCO] = strdup("bt-sco");
535 backend_table[SND_DEVICE_OUT_HDMI] = strdup("hdmi");
536 backend_table[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = strdup("speaker-and-hdmi");
537 backend_table[SND_DEVICE_OUT_BT_SCO_WB] = strdup("bt-sco-wb");
538 backend_table[SND_DEVICE_IN_BT_SCO_MIC_WB] = strdup("bt-sco-wb");
539
540 if (my_data->ext_speaker) {
541 backend_table[SND_DEVICE_OUT_SPEAKER] = strdup("speaker");
542 backend_table[SND_DEVICE_OUT_VOICE_SPEAKER] = strdup("speaker");
543 backend_table[SND_DEVICE_OUT_SPEAKER_REVERSE] = strdup("speaker");
544 backend_table[SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] =
545 strdup("speaker-and-headphones");
546 }
547
548 if (my_data->ext_earpiece) {
549 backend_table[SND_DEVICE_OUT_VOICE_HANDSET] = strdup("handset");
Eric Laurent9d0d3f12014-07-25 12:40:29 -0500550 backend_table[SND_DEVICE_OUT_VOICE_HAC_HANDSET] = strdup("handset");
Haynes Mathew George98c95622014-06-20 19:14:25 -0700551 backend_table[SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = strdup("handset");
552 backend_table[SND_DEVICE_OUT_HANDSET] = strdup("handset");
553 backend_table[SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = strdup("handset");
554 }
555}
556
Eric Laurentb23d5282013-05-14 15:27:20 -0700557void *platform_init(struct audio_device *adev)
558{
559 char value[PROPERTY_VALUE_MAX];
560 struct platform_data *my_data;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700561 int retry_num = 0, snd_card_num = 0;
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700562 const char *snd_card_name;
sangwoo1b9f4b32013-06-21 18:22:55 -0700563
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700564 while (snd_card_num < MAX_SND_CARD) {
565 adev->mixer = mixer_open(snd_card_num);
sangwoo1b9f4b32013-06-21 18:22:55 -0700566
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700567 while (!adev->mixer && retry_num < RETRY_NUMBER) {
568 usleep(RETRY_US);
569 adev->mixer = mixer_open(snd_card_num);
570 retry_num++;
571 }
572
573 if (!adev->mixer) {
574 ALOGE("%s: Unable to open the mixer card: %d", __func__,
575 snd_card_num);
576 retry_num = 0;
577 snd_card_num++;
578 continue;
579 }
580
581 snd_card_name = mixer_get_name(adev->mixer);
582 ALOGD("%s: snd_card_name: %s", __func__, snd_card_name);
583
584 adev->audio_route = audio_route_init(snd_card_num, MIXER_XML_PATH);
585 if (!adev->audio_route) {
586 ALOGE("%s: Failed to init audio route controls, aborting.", __func__);
587 return NULL;
588 }
589 adev->snd_card = snd_card_num;
590 ALOGD("%s: Opened sound card:%d", __func__, snd_card_num);
591 break;
sangwoo1b9f4b32013-06-21 18:22:55 -0700592 }
593
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700594 if (snd_card_num >= MAX_SND_CARD) {
595 ALOGE("%s: Unable to find correct sound card, aborting.", __func__);
sangwoo1b9f4b32013-06-21 18:22:55 -0700596 return NULL;
597 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700598
599 my_data = calloc(1, sizeof(struct platform_data));
600
601 my_data->adev = adev;
602 my_data->dualmic_config = DUALMIC_CONFIG_NONE;
603 my_data->fluence_in_spkr_mode = false;
604 my_data->fluence_in_voice_call = false;
605 my_data->fluence_in_voice_rec = false;
606
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500607 /*
608 * The default assumption is that earpiece (handset), speaker and headphones
609 * devices are connected to internal HW codec and communicated through
610 * slimbus backend. If any platform communicates with speaker or earpiece
611 * or headphones through non-slimbus backend such as MI2S or AUXPCM etc.,
612 * the ext_xxxx flags must be set accordingly.
613 */
614 if (strstr(snd_card_name, "tfa9890_stereo")) {
615 my_data->ext_speaker = true;
616 my_data->ext_earpiece = true;
617 } else if (strstr(snd_card_name, "tfa9890")) {
618 my_data->ext_speaker = true;
619 }
620
Eric Laurentb23d5282013-05-14 15:27:20 -0700621 property_get("persist.audio.dualmic.config",value,"");
622 if (!strcmp("broadside", value)) {
623 my_data->dualmic_config = DUALMIC_CONFIG_BROADSIDE;
624 adev->acdb_settings |= DMIC_FLAG;
625 } else if (!strcmp("endfire", value)) {
626 my_data->dualmic_config = DUALMIC_CONFIG_ENDFIRE;
627 adev->acdb_settings |= DMIC_FLAG;
628 }
629
630 if (my_data->dualmic_config != DUALMIC_CONFIG_NONE) {
631 property_get("persist.audio.fluence.voicecall",value,"");
632 if (!strcmp("true", value)) {
633 my_data->fluence_in_voice_call = true;
634 }
635
636 property_get("persist.audio.fluence.voicerec",value,"");
637 if (!strcmp("true", value)) {
638 my_data->fluence_in_voice_rec = true;
639 }
640
641 property_get("persist.audio.fluence.speaker",value,"");
642 if (!strcmp("true", value)) {
643 my_data->fluence_in_spkr_mode = true;
644 }
645 }
646
647 my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
648 if (my_data->acdb_handle == NULL) {
649 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_ACDB_LOADER);
650 } else {
651 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_ACDB_LOADER);
652 my_data->acdb_deallocate = (acdb_deallocate_t)dlsym(my_data->acdb_handle,
653 "acdb_loader_deallocate_ACDB");
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700654 if (!my_data->acdb_deallocate)
655 ALOGE("%s: Could not find the symbol acdb_loader_deallocate_ACDB from %s",
656 __func__, LIB_ACDB_LOADER);
657
Eric Laurentb23d5282013-05-14 15:27:20 -0700658 my_data->acdb_send_audio_cal = (acdb_send_audio_cal_t)dlsym(my_data->acdb_handle,
659 "acdb_loader_send_audio_cal");
660 if (!my_data->acdb_send_audio_cal)
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700661 ALOGE("%s: Could not find the symbol acdb_send_audio_cal from %s",
Eric Laurentb23d5282013-05-14 15:27:20 -0700662 __func__, LIB_ACDB_LOADER);
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700663
Eric Laurentb23d5282013-05-14 15:27:20 -0700664 my_data->acdb_send_voice_cal = (acdb_send_voice_cal_t)dlsym(my_data->acdb_handle,
665 "acdb_loader_send_voice_cal");
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700666 if (!my_data->acdb_send_voice_cal)
667 ALOGE("%s: Could not find the symbol acdb_loader_send_voice_cal from %s",
668 __func__, LIB_ACDB_LOADER);
669
670 my_data->acdb_reload_vocvoltable = (acdb_reload_vocvoltable_t)dlsym(my_data->acdb_handle,
671 "acdb_loader_reload_vocvoltable");
672 if (!my_data->acdb_reload_vocvoltable)
673 ALOGE("%s: Could not find the symbol acdb_loader_reload_vocvoltable from %s",
674 __func__, LIB_ACDB_LOADER);
675#ifdef PLATFORM_MSM8084
676 my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
677 "acdb_loader_init_v2");
678 if (my_data->acdb_init == NULL)
679 ALOGE("%s: dlsym error %s for acdb_loader_init_v2", __func__, dlerror());
680 else
Haynes Mathew George98c95622014-06-20 19:14:25 -0700681 my_data->acdb_init((char *)snd_card_name);
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700682#else
Eric Laurentb23d5282013-05-14 15:27:20 -0700683 my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
684 "acdb_loader_init_ACDB");
685 if (my_data->acdb_init == NULL)
686 ALOGE("%s: dlsym error %s for acdb_loader_init_ACDB", __func__, dlerror());
687 else
688 my_data->acdb_init();
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700689#endif
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700690
Eric Laurentb23d5282013-05-14 15:27:20 -0700691 }
692
Haynes Mathew George98c95622014-06-20 19:14:25 -0700693 set_platform_defaults(my_data);
694
695 /* Initialize platform specific ids and/or backends*/
696 platform_info_init();
697
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700698 /* load csd client */
699 platform_csd_init(my_data);
700
Eric Laurentb23d5282013-05-14 15:27:20 -0700701 return my_data;
702}
703
704void platform_deinit(void *platform)
705{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700706 struct platform_data *my_data = (struct platform_data *)platform;
707 close_csd_client(my_data->csd);
Eric Laurentb23d5282013-05-14 15:27:20 -0700708 free(platform);
709}
710
711const char *platform_get_snd_device_name(snd_device_t snd_device)
712{
713 if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX)
714 return device_table[snd_device];
715 else
716 return "";
717}
718
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500719void platform_add_backend_name(void *platform, char *mixer_path,
720 snd_device_t snd_device)
Eric Laurentb23d5282013-05-14 15:27:20 -0700721{
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500722 struct platform_data *my_data = (struct platform_data *)platform;
723
Haynes Mathew George98c95622014-06-20 19:14:25 -0700724 if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) {
725 ALOGE("%s: Invalid snd_device = %d", __func__, snd_device);
726 return;
Ravi Kumar Alamanda1de6e5a2014-06-19 21:55:39 -0500727 }
Haynes Mathew George98c95622014-06-20 19:14:25 -0700728
729 const char * suffix = backend_table[snd_device];
730
731 if (suffix != NULL) {
732 strcat(mixer_path, " ");
733 strcat(mixer_path, suffix);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500734 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700735}
736
737int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type)
738{
739 int device_id;
740 if (device_type == PCM_PLAYBACK)
741 device_id = pcm_device_table[usecase][0];
742 else
743 device_id = pcm_device_table[usecase][1];
744 return device_id;
745}
746
Haynes Mathew George98c95622014-06-20 19:14:25 -0700747static int find_index(const struct name_to_index * table, int32_t len,
748 const char * name)
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700749{
750 int ret = 0;
Haynes Mathew George98c95622014-06-20 19:14:25 -0700751 int32_t i;
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700752
Haynes Mathew George98c95622014-06-20 19:14:25 -0700753 if (table == NULL) {
754 ALOGE("%s: table is NULL", __func__);
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700755 ret = -ENODEV;
756 goto done;
757 }
758
Haynes Mathew George98c95622014-06-20 19:14:25 -0700759 if (name == NULL) {
760 ALOGE("null key");
761 ret = -ENODEV;
762 goto done;
763 }
764
765 for (i=0; i < len; i++) {
766 if (!strcmp(table[i].name, name)) {
767 ret = table[i].index;
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700768 goto done;
769 }
770 }
Haynes Mathew George98c95622014-06-20 19:14:25 -0700771 ALOGE("%s: Could not find index for name = %s",
772 __func__, name);
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700773 ret = -ENODEV;
774done:
775 return ret;
776}
777
Haynes Mathew George98c95622014-06-20 19:14:25 -0700778int platform_get_snd_device_index(char *device_name)
779{
780 return find_index(snd_device_name_index, SND_DEVICE_MAX, device_name);
781}
782
783int platform_get_usecase_index(const char *usecase_name)
784{
785 return find_index(usecase_name_index, AUDIO_USECASE_MAX, usecase_name);
786}
787
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700788int platform_set_snd_device_acdb_id(snd_device_t snd_device, unsigned int acdb_id)
789{
790 int ret = 0;
791
792 if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) {
793 ALOGE("%s: Invalid snd_device = %d",
794 __func__, snd_device);
795 ret = -EINVAL;
796 goto done;
797 }
798
799 acdb_device_table[snd_device] = acdb_id;
800done:
801 return ret;
802}
803
Eric Laurentb23d5282013-05-14 15:27:20 -0700804int platform_send_audio_calibration(void *platform, snd_device_t snd_device)
805{
806 struct platform_data *my_data = (struct platform_data *)platform;
807 int acdb_dev_id, acdb_dev_type;
808
809 acdb_dev_id = acdb_device_table[snd_device];
810 if (acdb_dev_id < 0) {
811 ALOGE("%s: Could not find acdb id for device(%d)",
812 __func__, snd_device);
813 return -EINVAL;
814 }
815 if (my_data->acdb_send_audio_cal) {
Eric Laurent994a6932013-07-17 11:51:42 -0700816 ("%s: sending audio calibration for snd_device(%d) acdb_id(%d)",
Eric Laurentb23d5282013-05-14 15:27:20 -0700817 __func__, snd_device, acdb_dev_id);
818 if (snd_device >= SND_DEVICE_OUT_BEGIN &&
819 snd_device < SND_DEVICE_OUT_END)
820 acdb_dev_type = ACDB_DEV_TYPE_OUT;
821 else
822 acdb_dev_type = ACDB_DEV_TYPE_IN;
823 my_data->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type);
824 }
825 return 0;
826}
827
828int platform_switch_voice_call_device_pre(void *platform)
829{
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700830 struct platform_data *my_data = (struct platform_data *)platform;
831 int ret = 0;
832
833 if (my_data->csd != NULL &&
834 my_data->adev->mode == AUDIO_MODE_IN_CALL) {
835 /* This must be called before disabling mixer controls on APQ side */
836 ret = my_data->csd->disable_device();
837 if (ret < 0) {
838 ALOGE("%s: csd_client_disable_device, failed, error %d",
839 __func__, ret);
840 }
841 }
842 return ret;
843}
844
845int platform_switch_voice_call_enable_device_config(void *platform,
846 snd_device_t out_snd_device,
847 snd_device_t in_snd_device)
848{
849 struct platform_data *my_data = (struct platform_data *)platform;
850 int acdb_rx_id, acdb_tx_id;
851 int ret = 0;
852
853 if (my_data->csd == NULL)
854 return ret;
855
856 acdb_rx_id = acdb_device_table[out_snd_device];
857
858 acdb_tx_id = acdb_device_table[in_snd_device];
859
860 if (acdb_rx_id > 0 && acdb_tx_id > 0) {
861 ret = my_data->csd->enable_device_config(acdb_rx_id, acdb_tx_id);
862 if (ret < 0) {
863 ALOGE("%s: csd_enable_device_config, failed, error %d",
864 __func__, ret);
865 }
866 } else {
867 ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__,
868 acdb_rx_id, acdb_tx_id);
869 }
870
871 return ret;
Eric Laurentb23d5282013-05-14 15:27:20 -0700872}
873
874int platform_switch_voice_call_device_post(void *platform,
875 snd_device_t out_snd_device,
876 snd_device_t in_snd_device)
877{
878 struct platform_data *my_data = (struct platform_data *)platform;
879 int acdb_rx_id, acdb_tx_id;
880
881 if (my_data->acdb_send_voice_cal == NULL) {
882 ALOGE("%s: dlsym error for acdb_send_voice_call", __func__);
883 } else {
884 acdb_rx_id = acdb_device_table[out_snd_device];
885 acdb_tx_id = acdb_device_table[in_snd_device];
886
887 if (acdb_rx_id > 0 && acdb_tx_id > 0)
888 my_data->acdb_send_voice_cal(acdb_rx_id, acdb_tx_id);
889 else
890 ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__,
891 acdb_rx_id, acdb_tx_id);
892 }
893
894 return 0;
895}
896
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700897int platform_switch_voice_call_usecase_route_post(void *platform,
898 snd_device_t out_snd_device,
899 snd_device_t in_snd_device)
900{
901 struct platform_data *my_data = (struct platform_data *)platform;
902 int acdb_rx_id, acdb_tx_id;
903 int ret = 0;
904
905 if (my_data->csd == NULL)
906 return ret;
907
908 acdb_rx_id = acdb_device_table[out_snd_device];
909
910 acdb_tx_id = acdb_device_table[in_snd_device];
911
912 if (acdb_rx_id > 0 && acdb_tx_id > 0) {
913 ret = my_data->csd->enable_device(acdb_rx_id, acdb_tx_id,
914 my_data->adev->acdb_settings);
915 if (ret < 0) {
916 ALOGE("%s: csd_enable_device, failed, error %d", __func__, ret);
917 }
918 } else {
919 ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__,
920 acdb_rx_id, acdb_tx_id);
921 }
922
923 return ret;
924}
925
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700926int platform_start_voice_call(void *platform, uint32_t vsid)
Eric Laurentb23d5282013-05-14 15:27:20 -0700927{
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700928 struct platform_data *my_data = (struct platform_data *)platform;
929 int ret = 0;
930
931 if (my_data->csd != NULL) {
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700932 ret = my_data->csd->start_voice(vsid);
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700933 if (ret < 0) {
934 ALOGE("%s: csd_start_voice error %d\n", __func__, ret);
935 }
936 }
937 return ret;
Eric Laurentb23d5282013-05-14 15:27:20 -0700938}
939
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700940int platform_stop_voice_call(void *platform, uint32_t vsid)
Eric Laurentb23d5282013-05-14 15:27:20 -0700941{
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700942 struct platform_data *my_data = (struct platform_data *)platform;
943 int ret = 0;
944
945 if (my_data->csd != NULL) {
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700946 ret = my_data->csd->stop_voice(vsid);
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700947 if (ret < 0) {
948 ALOGE("%s: csd_stop_voice error %d\n", __func__, ret);
949 }
950 }
951 return ret;
Eric Laurentb23d5282013-05-14 15:27:20 -0700952}
953
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700954int platform_get_sample_rate(void *platform, uint32_t *rate)
955{
956 struct platform_data *my_data = (struct platform_data *)platform;
957 int ret = 0;
958
959 if (my_data->csd != NULL) {
960 ret = my_data->csd->get_sample_rate(rate);
961 if (ret < 0) {
962 ALOGE("%s: csd_get_sample_rate error %d\n", __func__, ret);
963 }
964 }
965 return ret;
966}
967
Eric Laurentb23d5282013-05-14 15:27:20 -0700968int platform_set_voice_volume(void *platform, int volume)
969{
970 struct platform_data *my_data = (struct platform_data *)platform;
971 struct audio_device *adev = my_data->adev;
972 struct mixer_ctl *ctl;
sangwoo53b2cf02013-07-25 19:18:44 -0700973 const char *mixer_ctl_name = "Voice Rx Gain";
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700974 int vol_index = 0, ret = 0;
975 uint32_t set_values[ ] = {0,
976 ALL_SESSION_VSID,
977 DEFAULT_VOLUME_RAMP_DURATION_MS};
Eric Laurentb23d5282013-05-14 15:27:20 -0700978
979 // Voice volume levels are mapped to adsp volume levels as follows.
980 // 100 -> 5, 80 -> 4, 60 -> 3, 40 -> 2, 20 -> 1 0 -> 0
981 // But this values don't changed in kernel. So, below change is need.
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700982 vol_index = (int)percent_to_index(volume, MIN_VOL_INDEX, MAX_VOL_INDEX);
983 set_values[0] = vol_index;
Eric Laurentb23d5282013-05-14 15:27:20 -0700984
985 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
986 if (!ctl) {
987 ALOGE("%s: Could not get ctl for mixer cmd - %s",
988 __func__, mixer_ctl_name);
989 return -EINVAL;
990 }
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700991 ALOGV("Setting voice volume index: %d", set_values[0]);
992 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
993
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700994 if (my_data->csd != NULL) {
995 ret = my_data->csd->volume(ALL_SESSION_VSID, volume,
996 DEFAULT_VOLUME_RAMP_DURATION_MS);
997 if (ret < 0) {
998 ALOGE("%s: csd_volume error %d", __func__, ret);
999 }
1000 }
1001 return ret;
Eric Laurentb23d5282013-05-14 15:27:20 -07001002}
1003
1004int platform_set_mic_mute(void *platform, bool state)
1005{
1006 struct platform_data *my_data = (struct platform_data *)platform;
1007 struct audio_device *adev = my_data->adev;
1008 struct mixer_ctl *ctl;
1009 const char *mixer_ctl_name = "Voice Tx Mute";
sangwoo53b2cf02013-07-25 19:18:44 -07001010 int ret = 0;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001011 uint32_t set_values[ ] = {0,
1012 ALL_SESSION_VSID,
1013 DEFAULT_MUTE_RAMP_DURATION_MS};
Eric Laurentb23d5282013-05-14 15:27:20 -07001014
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001015 if (adev->mode != AUDIO_MODE_IN_CALL)
1016 return 0;
1017
1018 set_values[0] = state;
1019 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1020 if (!ctl) {
1021 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1022 __func__, mixer_ctl_name);
1023 return -EINVAL;
1024 }
1025 ALOGV("Setting voice mute state: %d", state);
1026 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1027
1028 if (my_data->csd != NULL) {
1029 ret = my_data->csd->mic_mute(ALL_SESSION_VSID, state,
1030 DEFAULT_MUTE_RAMP_DURATION_MS);
sangwoo53b2cf02013-07-25 19:18:44 -07001031 if (ret < 0) {
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001032 ALOGE("%s: csd_mic_mute error %d", __func__, ret);
sangwoo53b2cf02013-07-25 19:18:44 -07001033 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001034 }
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001035 return ret;
1036}
Eric Laurentb23d5282013-05-14 15:27:20 -07001037
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001038int platform_set_device_mute(void *platform, bool state, char *dir)
1039{
1040 struct platform_data *my_data = (struct platform_data *)platform;
1041 struct audio_device *adev = my_data->adev;
1042 struct mixer_ctl *ctl;
1043 char *mixer_ctl_name = NULL;
1044 int ret = 0;
1045 uint32_t set_values[ ] = {0,
1046 ALL_SESSION_VSID,
1047 0};
1048 if(dir == NULL) {
1049 ALOGE("%s: Invalid direction:%s", __func__, dir);
1050 return -EINVAL;
1051 }
1052
1053 if (!strncmp("rx", dir, sizeof("rx"))) {
1054 mixer_ctl_name = "Voice Rx Device Mute";
1055 } else if (!strncmp("tx", dir, sizeof("tx"))) {
1056 mixer_ctl_name = "Voice Tx Device Mute";
1057 } else {
1058 return -EINVAL;
1059 }
1060
1061 set_values[0] = state;
1062 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1063 if (!ctl) {
1064 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1065 __func__, mixer_ctl_name);
1066 return -EINVAL;
1067 }
1068
1069 ALOGV("%s: Setting device mute state: %d, mixer ctrl:%s",
1070 __func__,state, mixer_ctl_name);
1071 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1072
1073 return ret;
Eric Laurentb23d5282013-05-14 15:27:20 -07001074}
1075
1076snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices)
1077{
1078 struct platform_data *my_data = (struct platform_data *)platform;
1079 struct audio_device *adev = my_data->adev;
1080 audio_mode_t mode = adev->mode;
1081 snd_device_t snd_device = SND_DEVICE_NONE;
1082
1083 ALOGV("%s: enter: output devices(%#x)", __func__, devices);
1084 if (devices == AUDIO_DEVICE_NONE ||
1085 devices & AUDIO_DEVICE_BIT_IN) {
1086 ALOGV("%s: Invalid output devices (%#x)", __func__, devices);
1087 goto exit;
1088 }
1089
1090 if (mode == AUDIO_MODE_IN_CALL) {
1091 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
1092 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001093 if (adev->voice.tty_mode == TTY_MODE_FULL)
Eric Laurentb23d5282013-05-14 15:27:20 -07001094 snd_device = SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001095 else if (adev->voice.tty_mode == TTY_MODE_VCO)
Eric Laurentb23d5282013-05-14 15:27:20 -07001096 snd_device = SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001097 else if (adev->voice.tty_mode == TTY_MODE_HCO)
Eric Laurentb23d5282013-05-14 15:27:20 -07001098 snd_device = SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET;
1099 else
1100 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES;
1101 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07001102 if (adev->bt_wb_speech_enabled) {
1103 snd_device = SND_DEVICE_OUT_BT_SCO_WB;
1104 } else {
1105 snd_device = SND_DEVICE_OUT_BT_SCO;
1106 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001107 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
1108 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
1109 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
Eric Laurent9d0d3f12014-07-25 12:40:29 -05001110 if(adev->voice.hac)
1111 snd_device = SND_DEVICE_OUT_VOICE_HAC_HANDSET;
1112 else if (is_operator_tmus())
Eric Laurentb23d5282013-05-14 15:27:20 -07001113 snd_device = SND_DEVICE_OUT_VOICE_HANDSET_TMUS;
1114 else
Eric Laurentb4d368e2014-06-25 10:21:54 -05001115 snd_device = SND_DEVICE_OUT_VOICE_HANDSET;
Eric Laurentb23d5282013-05-14 15:27:20 -07001116 }
1117 if (snd_device != SND_DEVICE_NONE) {
1118 goto exit;
1119 }
1120 }
1121
1122 if (popcount(devices) == 2) {
1123 if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
1124 AUDIO_DEVICE_OUT_SPEAKER)) {
1125 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
1126 } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
1127 AUDIO_DEVICE_OUT_SPEAKER)) {
1128 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
1129 } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL |
1130 AUDIO_DEVICE_OUT_SPEAKER)) {
1131 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
1132 } else {
1133 ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
1134 goto exit;
1135 }
1136 if (snd_device != SND_DEVICE_NONE) {
1137 goto exit;
1138 }
1139 }
1140
1141 if (popcount(devices) != 1) {
1142 ALOGE("%s: Invalid output devices(%#x)", __func__, devices);
1143 goto exit;
1144 }
1145
1146 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
1147 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
1148 snd_device = SND_DEVICE_OUT_HEADPHONES;
1149 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
1150 if (adev->speaker_lr_swap)
1151 snd_device = SND_DEVICE_OUT_SPEAKER_REVERSE;
1152 else
1153 snd_device = SND_DEVICE_OUT_SPEAKER;
1154 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07001155 if (adev->bt_wb_speech_enabled) {
1156 snd_device = SND_DEVICE_OUT_BT_SCO_WB;
1157 } else {
1158 snd_device = SND_DEVICE_OUT_BT_SCO;
1159 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001160 } else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1161 snd_device = SND_DEVICE_OUT_HDMI ;
1162 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
Eric Laurent9d0d3f12014-07-25 12:40:29 -05001163 /*HAC support for voice-ish audio (eg visual voicemail)*/
1164 if(adev->voice.hac)
1165 snd_device = SND_DEVICE_OUT_VOICE_HAC_HANDSET;
1166 else
1167 snd_device = SND_DEVICE_OUT_HANDSET;
Eric Laurentb23d5282013-05-14 15:27:20 -07001168 } else {
1169 ALOGE("%s: Unknown device(s) %#x", __func__, devices);
1170 }
1171exit:
1172 ALOGV("%s: exit: snd_device(%s)", __func__, device_table[snd_device]);
1173 return snd_device;
1174}
1175
1176snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device)
1177{
1178 struct platform_data *my_data = (struct platform_data *)platform;
1179 struct audio_device *adev = my_data->adev;
1180 audio_source_t source = (adev->active_input == NULL) ?
1181 AUDIO_SOURCE_DEFAULT : adev->active_input->source;
1182
1183 audio_mode_t mode = adev->mode;
1184 audio_devices_t in_device = ((adev->active_input == NULL) ?
1185 AUDIO_DEVICE_NONE : adev->active_input->device)
1186 & ~AUDIO_DEVICE_BIT_IN;
1187 audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
1188 AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
1189 snd_device_t snd_device = SND_DEVICE_NONE;
1190
1191 ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
1192 __func__, out_device, in_device);
1193 if (mode == AUDIO_MODE_IN_CALL) {
1194 if (out_device == AUDIO_DEVICE_NONE) {
1195 ALOGE("%s: No output device set for voice call", __func__);
1196 goto exit;
1197 }
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001198 if (adev->voice.tty_mode != TTY_MODE_OFF) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001199 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
1200 out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001201 switch (adev->voice.tty_mode) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001202 case TTY_MODE_FULL:
1203 snd_device = SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC;
1204 break;
1205 case TTY_MODE_VCO:
1206 snd_device = SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC;
1207 break;
1208 case TTY_MODE_HCO:
1209 snd_device = SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC;
1210 break;
1211 default:
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001212 ALOGE("%s: Invalid TTY mode (%#x)", __func__, adev->voice.tty_mode);
Eric Laurentb23d5282013-05-14 15:27:20 -07001213 }
1214 goto exit;
1215 }
1216 }
1217 if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
1218 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
1219 if (my_data->fluence_in_voice_call == false) {
1220 snd_device = SND_DEVICE_IN_HANDSET_MIC;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001221 set_echo_reference(adev->mixer, "SLIM_RX");
Eric Laurentb23d5282013-05-14 15:27:20 -07001222 } else {
1223 if (my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
1224 if (is_operator_tmus())
1225 snd_device = SND_DEVICE_IN_VOICE_DMIC_EF_TMUS;
1226 else
1227 snd_device = SND_DEVICE_IN_VOICE_DMIC_EF;
1228 } else if(my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE)
1229 snd_device = SND_DEVICE_IN_VOICE_DMIC_BS;
1230 else
1231 snd_device = SND_DEVICE_IN_HANDSET_MIC;
1232 }
1233 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
1234 snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
1235 } else if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07001236 if (adev->bt_wb_speech_enabled) {
1237 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
1238 } else {
1239 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
1240 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001241 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
1242 if (my_data->fluence_in_voice_call && my_data->fluence_in_spkr_mode &&
1243 my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
1244 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF;
1245 } else if (my_data->fluence_in_voice_call && my_data->fluence_in_spkr_mode &&
1246 my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE) {
1247 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS;
1248 } else {
1249 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
1250 }
1251 }
1252 } else if (source == AUDIO_SOURCE_CAMCORDER) {
1253 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
1254 in_device & AUDIO_DEVICE_IN_BACK_MIC) {
1255 snd_device = SND_DEVICE_IN_CAMCORDER_MIC;
1256 }
1257 } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) {
1258 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
1259 if (my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
1260 if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
1261 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_EF;
1262 else if (my_data->fluence_in_voice_rec)
1263 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE;
1264 } else if (my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE) {
1265 if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
1266 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_BS;
1267 else if (my_data->fluence_in_voice_rec)
1268 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE;
1269 }
1270
1271 if (snd_device == SND_DEVICE_NONE) {
1272 snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
1273 }
1274 }
1275 } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1276 if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
1277 in_device = AUDIO_DEVICE_IN_BACK_MIC;
1278 if (adev->active_input) {
1279 if (adev->active_input->enable_aec) {
1280 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
1281 snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
1282 } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
1283 snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
1284 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
1285 snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
1286 }
1287 set_echo_reference(adev->mixer, "SLIM_RX");
1288 } else
1289 set_echo_reference(adev->mixer, "NONE");
1290 }
1291 } else if (source == AUDIO_SOURCE_DEFAULT) {
1292 goto exit;
1293 }
1294
1295
1296 if (snd_device != SND_DEVICE_NONE) {
1297 goto exit;
1298 }
1299
1300 if (in_device != AUDIO_DEVICE_NONE &&
1301 !(in_device & AUDIO_DEVICE_IN_VOICE_CALL) &&
1302 !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) {
1303 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
1304 snd_device = SND_DEVICE_IN_HANDSET_MIC;
1305 } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
1306 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
1307 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
1308 snd_device = SND_DEVICE_IN_HEADSET_MIC;
1309 } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07001310 if (adev->bt_wb_speech_enabled) {
1311 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
1312 } else {
1313 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
1314 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001315 } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) {
1316 snd_device = SND_DEVICE_IN_HDMI_MIC;
1317 } else {
1318 ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
1319 ALOGW("%s: Using default handset-mic", __func__);
1320 snd_device = SND_DEVICE_IN_HANDSET_MIC;
1321 }
1322 } else {
1323 if (out_device & AUDIO_DEVICE_OUT_EARPIECE) {
1324 snd_device = SND_DEVICE_IN_HANDSET_MIC;
1325 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
1326 snd_device = SND_DEVICE_IN_HEADSET_MIC;
1327 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
1328 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
1329 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
1330 snd_device = SND_DEVICE_IN_HANDSET_MIC;
1331 } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07001332 if (adev->bt_wb_speech_enabled) {
1333 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
1334 } else {
1335 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
1336 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001337 } else if (out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1338 snd_device = SND_DEVICE_IN_HDMI_MIC;
1339 } else {
1340 ALOGE("%s: Unknown output device(s) %#x", __func__, out_device);
1341 ALOGW("%s: Using default handset-mic", __func__);
1342 snd_device = SND_DEVICE_IN_HANDSET_MIC;
1343 }
1344 }
1345exit:
1346 ALOGV("%s: exit: in_snd_device(%s)", __func__, device_table[snd_device]);
1347 return snd_device;
1348}
1349
1350int platform_set_hdmi_channels(void *platform, int channel_count)
1351{
1352 struct platform_data *my_data = (struct platform_data *)platform;
1353 struct audio_device *adev = my_data->adev;
1354 struct mixer_ctl *ctl;
1355 const char *channel_cnt_str = NULL;
1356 const char *mixer_ctl_name = "HDMI_RX Channels";
1357 switch (channel_count) {
1358 case 8:
1359 channel_cnt_str = "Eight"; break;
1360 case 7:
1361 channel_cnt_str = "Seven"; break;
1362 case 6:
1363 channel_cnt_str = "Six"; break;
1364 case 5:
1365 channel_cnt_str = "Five"; break;
1366 case 4:
1367 channel_cnt_str = "Four"; break;
1368 case 3:
1369 channel_cnt_str = "Three"; break;
1370 default:
1371 channel_cnt_str = "Two"; break;
1372 }
1373 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1374 if (!ctl) {
1375 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1376 __func__, mixer_ctl_name);
1377 return -EINVAL;
1378 }
1379 ALOGV("HDMI channel count: %s", channel_cnt_str);
1380 mixer_ctl_set_enum_by_string(ctl, channel_cnt_str);
1381 return 0;
1382}
1383
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001384int platform_edid_get_max_channels(void *platform)
Eric Laurentb23d5282013-05-14 15:27:20 -07001385{
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001386 struct platform_data *my_data = (struct platform_data *)platform;
1387 struct audio_device *adev = my_data->adev;
Eric Laurentb23d5282013-05-14 15:27:20 -07001388 char block[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE];
1389 char *sad = block;
1390 int num_audio_blocks;
1391 int channel_count;
1392 int max_channels = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001393 int i, ret, count;
Eric Laurentb23d5282013-05-14 15:27:20 -07001394
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001395 struct mixer_ctl *ctl;
1396
1397 ctl = mixer_get_ctl_by_name(adev->mixer, AUDIO_DATA_BLOCK_MIXER_CTL);
1398 if (!ctl) {
1399 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1400 __func__, AUDIO_DATA_BLOCK_MIXER_CTL);
Eric Laurentb23d5282013-05-14 15:27:20 -07001401 return 0;
1402 }
1403
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001404 mixer_ctl_update(ctl);
1405
1406 count = mixer_ctl_get_num_values(ctl);
Eric Laurentb23d5282013-05-14 15:27:20 -07001407
1408 /* Read SAD blocks, clamping the maximum size for safety */
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001409 if (count > (int)sizeof(block))
1410 count = (int)sizeof(block);
Eric Laurentb23d5282013-05-14 15:27:20 -07001411
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001412 ret = mixer_ctl_get_array(ctl, block, count);
1413 if (ret != 0) {
1414 ALOGE("%s: mixer_ctl_get_array() failed to get EDID info", __func__);
1415 return 0;
1416 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001417
1418 /* Calculate the number of SAD blocks */
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001419 num_audio_blocks = count / SAD_BLOCK_SIZE;
Eric Laurentb23d5282013-05-14 15:27:20 -07001420
1421 for (i = 0; i < num_audio_blocks; i++) {
1422 /* Only consider LPCM blocks */
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001423 if ((sad[0] >> 3) != EDID_FORMAT_LPCM) {
1424 sad += 3;
Eric Laurentb23d5282013-05-14 15:27:20 -07001425 continue;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001426 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001427
1428 channel_count = (sad[0] & 0x7) + 1;
1429 if (channel_count > max_channels)
1430 max_channels = channel_count;
1431
1432 /* Advance to next block */
1433 sad += 3;
1434 }
1435
1436 return max_channels;
1437}
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07001438
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001439int platform_set_incall_recording_session_id(void *platform,
1440 uint32_t session_id, int rec_mode)
1441{
1442 int ret = 0;
1443 struct platform_data *my_data = (struct platform_data *)platform;
1444 struct audio_device *adev = my_data->adev;
1445 struct mixer_ctl *ctl;
1446 const char *mixer_ctl_name = "Voc VSID";
1447 int num_ctl_values;
1448 int i;
1449
1450 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1451 if (!ctl) {
1452 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1453 __func__, mixer_ctl_name);
1454 ret = -EINVAL;
1455 } else {
1456 num_ctl_values = mixer_ctl_get_num_values(ctl);
1457 for (i = 0; i < num_ctl_values; i++) {
1458 if (mixer_ctl_set_value(ctl, i, session_id)) {
1459 ALOGV("Error: invalid session_id: %x", session_id);
1460 ret = -EINVAL;
1461 break;
1462 }
1463 }
1464 }
1465
1466 if (my_data->csd != NULL) {
1467 ret = my_data->csd->start_record(ALL_SESSION_VSID, rec_mode);
1468 if (ret < 0) {
1469 ALOGE("%s: csd_client_start_record failed, error %d",
1470 __func__, ret);
1471 }
1472 }
1473
1474 return ret;
1475}
1476
1477int platform_stop_incall_recording_usecase(void *platform)
1478{
1479 int ret = 0;
1480 struct platform_data *my_data = (struct platform_data *)platform;
1481
1482 if (my_data->csd != NULL) {
1483 ret = my_data->csd->stop_record(ALL_SESSION_VSID);
1484 if (ret < 0) {
1485 ALOGE("%s: csd_client_stop_record failed, error %d",
1486 __func__, ret);
1487 }
1488 }
1489
1490 return ret;
1491}
1492
1493int platform_start_incall_music_usecase(void *platform)
1494{
1495 int ret = 0;
1496 struct platform_data *my_data = (struct platform_data *)platform;
1497
1498 if (my_data->csd != NULL) {
1499 ret = my_data->csd->start_playback(ALL_SESSION_VSID);
1500 if (ret < 0) {
1501 ALOGE("%s: csd_client_start_playback failed, error %d",
1502 __func__, ret);
1503 }
1504 }
1505
1506 return ret;
1507}
1508
1509int platform_stop_incall_music_usecase(void *platform)
1510{
1511 int ret = 0;
1512 struct platform_data *my_data = (struct platform_data *)platform;
1513
1514 if (my_data->csd != NULL) {
1515 ret = my_data->csd->stop_playback(ALL_SESSION_VSID);
1516 if (ret < 0) {
1517 ALOGE("%s: csd_client_stop_playback failed, error %d",
1518 __func__, ret);
1519 }
1520 }
1521
1522 return ret;
1523}
1524
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07001525/* Delay in Us */
1526int64_t platform_render_latency(audio_usecase_t usecase)
1527{
1528 switch (usecase) {
1529 case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER:
1530 return DEEP_BUFFER_PLATFORM_DELAY;
1531 case USECASE_AUDIO_PLAYBACK_LOW_LATENCY:
1532 return LOW_LATENCY_PLATFORM_DELAY;
1533 default:
1534 return 0;
1535 }
1536}
Haynes Mathew George98c95622014-06-20 19:14:25 -07001537
1538int platform_set_snd_device_backend(snd_device_t device, const char *backend)
1539{
1540 int ret = 0;
1541
1542 if ((device < SND_DEVICE_MIN) || (device >= SND_DEVICE_MAX)) {
1543 ALOGE("%s: Invalid snd_device = %d",
1544 __func__, device);
1545 ret = -EINVAL;
1546 goto done;
1547 }
1548
1549 if (backend_table[device]) {
1550 free(backend_table[device]);
1551 }
1552 backend_table[device] = strdup(backend);
1553done:
1554 return ret;
1555}
1556
1557int platform_set_usecase_pcm_id(audio_usecase_t usecase, int32_t type, int32_t pcm_id)
1558{
1559 int ret = 0;
1560 if ((usecase <= USECASE_INVALID) || (usecase >= AUDIO_USECASE_MAX)) {
1561 ALOGE("%s: invalid usecase case idx %d", __func__, usecase);
1562 ret = -EINVAL;
1563 goto done;
1564 }
1565
1566 if ((type != 0) && (type != 1)) {
1567 ALOGE("%s: invalid usecase type", __func__);
1568 ret = -EINVAL;
1569 }
1570 pcm_device_table[usecase][type] = pcm_id;
1571done:
1572 return ret;
1573}