blob: 18882535864afbb57db9a121fcd5f3dd8f0a50bd [file] [log] [blame]
Eric Laurentb23d5282013-05-14 15:27:20 -07001/*
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07002 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
3 * Not a Contribution.
4 *
Eric Laurentb23d5282013-05-14 15:27:20 -07005 * Copyright (C) 2013 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20#define LOG_TAG "msm8974_platform"
21/*#define LOG_NDEBUG 0*/
22#define LOG_NDDEBUG 0
23
24#include <stdlib.h>
25#include <dlfcn.h>
26#include <cutils/log.h>
27#include <cutils/properties.h>
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070028#include <cutils/str_parms.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070029#include <audio_hw.h>
30#include <platform_api.h>
31#include "platform.h"
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070032#include "audio_extn.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070033
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -070034#define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
Eric Laurentb23d5282013-05-14 15:27:20 -070035#define LIB_ACDB_LOADER "libacdbloader.so"
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -070036#define AUDIO_DATA_BLOCK_MIXER_CTL "HDMI EDID"
Eric Laurentb23d5282013-05-14 15:27:20 -070037
Eric Laurentb23d5282013-05-14 15:27:20 -070038/*
Eric Laurentb23d5282013-05-14 15:27:20 -070039 * 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
sangwoo1b9f4b32013-06-21 18:22:55 -070051/* Retry for delay in FW loading*/
52#define RETRY_NUMBER 10
53#define RETRY_US 500000
54
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070055#define SAMPLE_RATE_8KHZ 8000
56#define SAMPLE_RATE_16KHZ 16000
57
sangwoo53b2cf02013-07-25 19:18:44 -070058#define MAX_VOL_INDEX 5
59#define MIN_VOL_INDEX 0
60#define percent_to_index(val, min, max) \
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070061 ((val) * ((max) - (min)) * 0.01 + (min) + .5)
62
63#define AUDIO_PARAMETER_KEY_FLUENCE_TYPE "fluence"
64#define AUDIO_PARAMETER_KEY_BTSCO "bt_samplerate"
65#define AUDIO_PARAMETER_KEY_SLOWTALK "st_enable"
sangwoo53b2cf02013-07-25 19:18:44 -070066
Eric Laurentb23d5282013-05-14 15:27:20 -070067struct audio_block_header
68{
69 int reserved;
70 int length;
71};
72
73typedef void (*acdb_deallocate_t)();
74typedef int (*acdb_init_t)();
75typedef void (*acdb_send_audio_cal_t)(int, int);
76typedef void (*acdb_send_voice_cal_t)(int, int);
77
Eric Laurentb23d5282013-05-14 15:27:20 -070078struct platform_data {
79 struct audio_device *adev;
80 bool fluence_in_spkr_mode;
81 bool fluence_in_voice_call;
82 bool fluence_in_voice_rec;
Mingming Yin8e5a4f62013-10-07 15:23:41 -070083 int fluence_type;
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070084 int btsco_sample_rate;
85 bool slowtalk;
Eric Laurentb23d5282013-05-14 15:27:20 -070086
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -070087 /* Audio calibration related functions */
Eric Laurentb23d5282013-05-14 15:27:20 -070088 void *acdb_handle;
89 acdb_init_t acdb_init;
90 acdb_deallocate_t acdb_deallocate;
91 acdb_send_audio_cal_t acdb_send_audio_cal;
92 acdb_send_voice_cal_t acdb_send_voice_cal;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -070093
94 void *hw_info;
Eric Laurentb23d5282013-05-14 15:27:20 -070095};
96
97static const int pcm_device_table[AUDIO_USECASE_MAX][2] = {
Mingming Yin8e5a4f62013-10-07 15:23:41 -070098 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {DEEP_BUFFER_PCM_DEVICE,
99 DEEP_BUFFER_PCM_DEVICE},
100 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
101 LOWLATENCY_PCM_DEVICE},
102 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {MULTI_CHANNEL_PCM_DEVICE,
103 MULTI_CHANNEL_PCM_DEVICE},
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700104 [USECASE_AUDIO_RECORD] = {AUDIO_RECORD_PCM_DEVICE, AUDIO_RECORD_PCM_DEVICE},
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700105 [USECASE_AUDIO_RECORD_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
106 LOWLATENCY_PCM_DEVICE},
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700107 [USECASE_AUDIO_PLAYBACK_FM] = {FM_PLAYBACK_PCM_DEVICE, FM_CAPTURE_PCM_DEVICE},
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700108 [USECASE_VOICE_CALL] = {VOICE_CALL_PCM_DEVICE, VOICE_CALL_PCM_DEVICE},
109 [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},
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700112 [USECASE_INCALL_REC_UPLINK] = {AUDIO_RECORD_PCM_DEVICE,
113 AUDIO_RECORD_PCM_DEVICE},
114 [USECASE_INCALL_REC_DOWNLINK] = {AUDIO_RECORD_PCM_DEVICE,
115 AUDIO_RECORD_PCM_DEVICE},
116 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = {AUDIO_RECORD_PCM_DEVICE,
117 AUDIO_RECORD_PCM_DEVICE},
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700118 [USECASE_INCALL_MUSIC_UPLINK] = {INCALL_MUSIC_UPLINK_PCM_DEVICE,
119 INCALL_MUSIC_UPLINK_PCM_DEVICE},
120 [USECASE_INCALL_MUSIC_UPLINK2] = {INCALL_MUSIC_UPLINK2_PCM_DEVICE,
121 INCALL_MUSIC_UPLINK2_PCM_DEVICE},
Eric Laurentb23d5282013-05-14 15:27:20 -0700122};
123
124/* Array to store sound devices */
125static const char * const device_table[SND_DEVICE_MAX] = {
126 [SND_DEVICE_NONE] = "none",
127 /* Playback sound devices */
128 [SND_DEVICE_OUT_HANDSET] = "handset",
129 [SND_DEVICE_OUT_SPEAKER] = "speaker",
130 [SND_DEVICE_OUT_SPEAKER_REVERSE] = "speaker-reverse",
131 [SND_DEVICE_OUT_HEADPHONES] = "headphones",
132 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones",
133 [SND_DEVICE_OUT_VOICE_HANDSET] = "voice-handset",
134 [SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker",
135 [SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones",
136 [SND_DEVICE_OUT_HDMI] = "hdmi",
137 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
138 [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700139 [SND_DEVICE_OUT_BT_SCO_WB] = "bt-sco-headset-wb",
Eric Laurentb23d5282013-05-14 15:27:20 -0700140 [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = "voice-handset-tmus",
141 [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = "voice-tty-full-headphones",
142 [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = "voice-tty-vco-headphones",
143 [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = "voice-tty-hco-handset",
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700144 [SND_DEVICE_OUT_AFE_PROXY] = "afe-proxy",
145 [SND_DEVICE_OUT_USB_HEADSET] = "usb-headphones",
146 [SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET] = "speaker-and-usb-headphones",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700147 [SND_DEVICE_OUT_TRANSMISSION_FM] = "transmission-fm",
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700148 [SND_DEVICE_OUT_ANC_HEADSET] = "anc-headphones",
149 [SND_DEVICE_OUT_ANC_FB_HEADSET] = "anc-fb-headphones",
150 [SND_DEVICE_OUT_VOICE_ANC_HEADSET] = "voice-anc-headphones",
151 [SND_DEVICE_OUT_VOICE_ANC_FB_HEADSET] = "voice-anc-fb-headphones",
152 [SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET] = "speaker-and-anc-headphones",
153 [SND_DEVICE_OUT_ANC_HANDSET] = "anc-handset",
Eric Laurentb23d5282013-05-14 15:27:20 -0700154
155 /* Capture sound devices */
156 [SND_DEVICE_IN_HANDSET_MIC] = "handset-mic",
157 [SND_DEVICE_IN_SPEAKER_MIC] = "speaker-mic",
158 [SND_DEVICE_IN_HEADSET_MIC] = "headset-mic",
159 [SND_DEVICE_IN_HANDSET_MIC_AEC] = "handset-mic",
160 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = "voice-speaker-mic",
161 [SND_DEVICE_IN_HEADSET_MIC_AEC] = "headset-mic",
162 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "voice-speaker-mic",
163 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "voice-headset-mic",
164 [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic",
165 [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700166 [SND_DEVICE_IN_BT_SCO_MIC_WB] = "bt-sco-mic-wb",
Eric Laurentb23d5282013-05-14 15:27:20 -0700167 [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic",
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700168 [SND_DEVICE_IN_VOICE_DMIC] = "voice-dmic-ef",
169 [SND_DEVICE_IN_VOICE_DMIC_TMUS] = "voice-dmic-ef-tmus",
170 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC] = "voice-speaker-dmic-ef",
Eric Laurentb23d5282013-05-14 15:27:20 -0700171 [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = "voice-tty-full-headset-mic",
172 [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = "voice-tty-vco-handset-mic",
173 [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = "voice-tty-hco-headset-mic",
174 [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic",
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700175 [SND_DEVICE_IN_VOICE_REC_DMIC] = "voice-rec-dmic-ef",
176 [SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE] = "voice-rec-dmic-ef-fluence",
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700177 [SND_DEVICE_IN_USB_HEADSET_MIC] = "usb-headset-mic",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700178 [SND_DEVICE_IN_CAPTURE_FM] = "capture-fm",
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700179 [SND_DEVICE_IN_AANC_HANDSET_MIC] = "aanc-handset-mic",
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -0700180 [SND_DEVICE_IN_QUAD_MIC] = "quad-mic",
Apoorv Raghuvanshi6bd8dbf2013-10-19 18:37:52 -0700181 [SND_DEVICE_IN_HANDSET_STEREO_DMIC] = "handset-stereo-dmic-ef",
182 [SND_DEVICE_IN_SPEAKER_STEREO_DMIC] = "speaker-stereo-dmic-ef",
Eric Laurentb23d5282013-05-14 15:27:20 -0700183};
184
185/* ACDB IDs (audio DSP path configuration IDs) for each sound device */
186static const int acdb_device_table[SND_DEVICE_MAX] = {
187 [SND_DEVICE_NONE] = -1,
188 [SND_DEVICE_OUT_HANDSET] = 7,
189 [SND_DEVICE_OUT_SPEAKER] = 15,
190 [SND_DEVICE_OUT_SPEAKER_REVERSE] = 15,
191 [SND_DEVICE_OUT_HEADPHONES] = 10,
192 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = 10,
193 [SND_DEVICE_OUT_VOICE_HANDSET] = 7,
194 [SND_DEVICE_OUT_VOICE_SPEAKER] = 15,
195 [SND_DEVICE_OUT_VOICE_HEADPHONES] = 10,
196 [SND_DEVICE_OUT_HDMI] = 18,
197 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 15,
198 [SND_DEVICE_OUT_BT_SCO] = 22,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700199 [SND_DEVICE_OUT_BT_SCO_WB] = 39,
sangwooc69476f2013-07-26 16:57:26 -0700200 [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = 88,
Eric Laurentb23d5282013-05-14 15:27:20 -0700201 [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = 17,
202 [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = 17,
203 [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = 37,
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700204 [SND_DEVICE_OUT_AFE_PROXY] = 0,
205 [SND_DEVICE_OUT_USB_HEADSET] = 0,
206 [SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET] = 14,
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700207 [SND_DEVICE_OUT_TRANSMISSION_FM] = 0,
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700208 [SND_DEVICE_OUT_ANC_HEADSET] = 26,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700209 [SND_DEVICE_OUT_ANC_FB_HEADSET] = 27,
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700210 [SND_DEVICE_OUT_VOICE_ANC_HEADSET] = 26,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700211 [SND_DEVICE_OUT_VOICE_ANC_FB_HEADSET] = 27,
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700212 [SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET] = 26,
213 [SND_DEVICE_OUT_ANC_HANDSET] = 103,
Eric Laurentb23d5282013-05-14 15:27:20 -0700214
215 [SND_DEVICE_IN_HANDSET_MIC] = 4,
216 [SND_DEVICE_IN_SPEAKER_MIC] = 4, /* ToDo: Check if this needs to changed to 11 */
217 [SND_DEVICE_IN_HEADSET_MIC] = 8,
218 [SND_DEVICE_IN_HANDSET_MIC_AEC] = 40,
219 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = 42,
220 [SND_DEVICE_IN_HEADSET_MIC_AEC] = 47,
221 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = 11,
222 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = 8,
223 [SND_DEVICE_IN_HDMI_MIC] = 4,
224 [SND_DEVICE_IN_BT_SCO_MIC] = 21,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700225 [SND_DEVICE_IN_BT_SCO_MIC_WB] = 38,
Eric Laurentb23d5282013-05-14 15:27:20 -0700226 [SND_DEVICE_IN_CAMCORDER_MIC] = 61,
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700227 [SND_DEVICE_IN_VOICE_DMIC] = 41,
228 [SND_DEVICE_IN_VOICE_DMIC_TMUS] = 89,
229 [SND_DEVICE_IN_VOICE_SPEAKER_DMIC] = 43,
Eric Laurentb23d5282013-05-14 15:27:20 -0700230 [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = 16,
231 [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = 36,
232 [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = 16,
233 [SND_DEVICE_IN_VOICE_REC_MIC] = 62,
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700234 [SND_DEVICE_IN_USB_HEADSET_MIC] = 44,
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700235 [SND_DEVICE_IN_CAPTURE_FM] = 0,
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700236 [SND_DEVICE_IN_AANC_HANDSET_MIC] = 104,
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -0700237 [SND_DEVICE_IN_QUAD_MIC] = 46,
Apoorv Raghuvanshi6bd8dbf2013-10-19 18:37:52 -0700238 [SND_DEVICE_IN_HANDSET_STEREO_DMIC] = 34,
239 [SND_DEVICE_IN_SPEAKER_STEREO_DMIC] = 35,
Eric Laurentb23d5282013-05-14 15:27:20 -0700240 /* TODO: Update with proper acdb ids */
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700241 [SND_DEVICE_IN_VOICE_REC_DMIC] = 62,
242 [SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE] = 6,
Eric Laurentb23d5282013-05-14 15:27:20 -0700243};
244
Haynes Mathew George7ff216f2013-09-11 19:51:41 -0700245#define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL)
246#define LOW_LATENCY_PLATFORM_DELAY (13*1000LL)
247
Eric Laurentb23d5282013-05-14 15:27:20 -0700248static pthread_once_t check_op_once_ctl = PTHREAD_ONCE_INIT;
249static bool is_tmus = false;
250
251static void check_operator()
252{
253 char value[PROPERTY_VALUE_MAX];
254 int mccmnc;
255 property_get("gsm.sim.operator.numeric",value,"0");
256 mccmnc = atoi(value);
257 ALOGD("%s: tmus mccmnc %d", __func__, mccmnc);
258 switch(mccmnc) {
259 /* TMUS MCC(310), MNC(490, 260, 026) */
260 case 310490:
261 case 310260:
262 case 310026:
sangwon.jeonb891db52013-09-14 17:39:15 +0900263 /* Add new TMUS MNC(800, 660, 580, 310, 270, 250, 240, 230, 220, 210, 200, 160) */
264 case 310800:
265 case 310660:
266 case 310580:
267 case 310310:
268 case 310270:
269 case 310250:
270 case 310240:
271 case 310230:
272 case 310220:
273 case 310210:
274 case 310200:
275 case 310160:
Eric Laurentb23d5282013-05-14 15:27:20 -0700276 is_tmus = true;
277 break;
278 }
279}
280
281bool is_operator_tmus()
282{
283 pthread_once(&check_op_once_ctl, check_operator);
284 return is_tmus;
285}
286
287static int set_echo_reference(struct mixer *mixer, const char* ec_ref)
288{
289 struct mixer_ctl *ctl;
290 const char *mixer_ctl_name = "EC_REF_RX";
291
292 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
293 if (!ctl) {
294 ALOGE("%s: Could not get ctl for mixer cmd - %s",
295 __func__, mixer_ctl_name);
296 return -EINVAL;
297 }
298 ALOGV("Setting EC Reference: %s", ec_ref);
299 mixer_ctl_set_enum_by_string(ctl, ec_ref);
300 return 0;
301}
302
303void *platform_init(struct audio_device *adev)
304{
305 char value[PROPERTY_VALUE_MAX];
306 struct platform_data *my_data;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700307 int retry_num = 0;
308 const char *snd_card_name;
sangwoo1b9f4b32013-06-21 18:22:55 -0700309
310 adev->mixer = mixer_open(MIXER_CARD);
311
312 while (!adev->mixer && retry_num < RETRY_NUMBER) {
313 usleep(RETRY_US);
314 adev->mixer = mixer_open(MIXER_CARD);
315 retry_num++;
316 }
317
318 if (!adev->mixer) {
319 ALOGE("Unable to open the mixer, aborting.");
320 return NULL;
321 }
322
323 adev->audio_route = audio_route_init(MIXER_CARD, MIXER_XML_PATH);
324 if (!adev->audio_route) {
325 ALOGE("%s: Failed to init audio route controls, aborting.", __func__);
326 return NULL;
327 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700328
329 my_data = calloc(1, sizeof(struct platform_data));
330
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700331 snd_card_name = mixer_get_name(adev->mixer);
332 my_data->hw_info = hw_info_init(snd_card_name);
333 if (!my_data->hw_info) {
334 ALOGE("%s: Failed to init hardware info", __func__);
335 }
336
Eric Laurentb23d5282013-05-14 15:27:20 -0700337 my_data->adev = adev;
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700338 my_data->btsco_sample_rate = SAMPLE_RATE_8KHZ;
Eric Laurentb23d5282013-05-14 15:27:20 -0700339 my_data->fluence_in_spkr_mode = false;
340 my_data->fluence_in_voice_call = false;
341 my_data->fluence_in_voice_rec = false;
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700342 my_data->fluence_type = FLUENCE_NONE;
Eric Laurentb23d5282013-05-14 15:27:20 -0700343
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700344 property_get("ro.qc.sdk.audio.fluencetype", value, "");
345 if (!strncmp("fluencepro", value, sizeof("fluencepro"))) {
346 my_data->fluence_type = FLUENCE_QUAD_MIC;
347 } else if (!strncmp("fluence", value, sizeof("fluence"))) {
348 my_data->fluence_type = FLUENCE_DUAL_MIC;
349 } else {
350 my_data->fluence_type = FLUENCE_NONE;
Eric Laurentb23d5282013-05-14 15:27:20 -0700351 }
352
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700353 if (my_data->fluence_type != FLUENCE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700354 property_get("persist.audio.fluence.voicecall",value,"");
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700355 if (!strncmp("true", value, sizeof("true"))) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700356 my_data->fluence_in_voice_call = true;
357 }
358
359 property_get("persist.audio.fluence.voicerec",value,"");
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700360 if (!strncmp("true", value, sizeof("true"))) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700361 my_data->fluence_in_voice_rec = true;
362 }
363
364 property_get("persist.audio.fluence.speaker",value,"");
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700365 if (!strncmp("true", value, sizeof("true"))) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700366 my_data->fluence_in_spkr_mode = true;
367 }
368 }
369
370 my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
371 if (my_data->acdb_handle == NULL) {
372 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_ACDB_LOADER);
373 } else {
374 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_ACDB_LOADER);
375 my_data->acdb_deallocate = (acdb_deallocate_t)dlsym(my_data->acdb_handle,
376 "acdb_loader_deallocate_ACDB");
377 my_data->acdb_send_audio_cal = (acdb_send_audio_cal_t)dlsym(my_data->acdb_handle,
378 "acdb_loader_send_audio_cal");
379 if (!my_data->acdb_send_audio_cal)
380 ALOGW("%s: Could not find the symbol acdb_send_audio_cal from %s",
381 __func__, LIB_ACDB_LOADER);
382 my_data->acdb_send_voice_cal = (acdb_send_voice_cal_t)dlsym(my_data->acdb_handle,
383 "acdb_loader_send_voice_cal");
384 my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
385 "acdb_loader_init_ACDB");
386 if (my_data->acdb_init == NULL)
387 ALOGE("%s: dlsym error %s for acdb_loader_init_ACDB", __func__, dlerror());
388 else
389 my_data->acdb_init();
390 }
391
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700392 /* init usb */
393 audio_extn_usb_init(adev);
394
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -0700395 /* Read one time ssr property */
396 audio_extn_ssr_update_enabled(adev);
397
Eric Laurentb23d5282013-05-14 15:27:20 -0700398 return my_data;
399}
400
401void platform_deinit(void *platform)
402{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700403 struct platform_data *my_data = (struct platform_data *)platform;
404
405 hw_info_deinit(my_data->hw_info);
Eric Laurentb23d5282013-05-14 15:27:20 -0700406 free(platform);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700407 /* deinit usb */
408 audio_extn_usb_deinit();
Eric Laurentb23d5282013-05-14 15:27:20 -0700409}
410
411const char *platform_get_snd_device_name(snd_device_t snd_device)
412{
413 if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX)
414 return device_table[snd_device];
415 else
416 return "";
417}
418
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700419int platform_get_snd_device_name_extn(void *platform, snd_device_t snd_device,
420 char *device_name)
421{
422 struct platform_data *my_data = (struct platform_data *)platform;
423
424 if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX) {
425 strlcpy(device_name, device_table[snd_device], DEVICE_NAME_MAX_SIZE);
426 hw_info_append_hw_type(my_data->hw_info, snd_device, device_name);
427 } else {
428 strlcpy(device_name, "", DEVICE_NAME_MAX_SIZE);
429 return -EINVAL;
430 }
431
432 return 0;
433}
434
Eric Laurentb23d5282013-05-14 15:27:20 -0700435void platform_add_backend_name(char *mixer_path, snd_device_t snd_device)
436{
437 if (snd_device == SND_DEVICE_IN_BT_SCO_MIC)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700438 strlcat(mixer_path, " bt-sco", MIXER_PATH_MAX_LENGTH);
439 else if (snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB)
440 strlcat(mixer_path, " bt-sco-wb", MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700441 else if(snd_device == SND_DEVICE_OUT_BT_SCO)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700442 strlcat(mixer_path, " bt-sco", MIXER_PATH_MAX_LENGTH);
443 else if(snd_device == SND_DEVICE_OUT_BT_SCO_WB)
444 strlcat(mixer_path, " bt-sco-wb", MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700445 else if (snd_device == SND_DEVICE_OUT_HDMI)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700446 strlcat(mixer_path, " hdmi", MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700447 else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HDMI)
448 strcat(mixer_path, " speaker-and-hdmi");
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700449 else if (snd_device == SND_DEVICE_OUT_AFE_PROXY)
450 strlcat(mixer_path, " afe-proxy", MIXER_PATH_MAX_LENGTH);
451 else if (snd_device == SND_DEVICE_OUT_USB_HEADSET)
452 strlcat(mixer_path, " usb-headphones", MIXER_PATH_MAX_LENGTH);
453 else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET)
454 strlcat(mixer_path, " speaker-and-usb-headphones",
455 MIXER_PATH_MAX_LENGTH);
456 else if (snd_device == SND_DEVICE_IN_USB_HEADSET_MIC)
457 strlcat(mixer_path, " usb-headset-mic", MIXER_PATH_MAX_LENGTH);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700458 else if (snd_device == SND_DEVICE_IN_CAPTURE_FM)
459 strlcat(mixer_path, " capture-fm", MIXER_PATH_MAX_LENGTH);
460 else if (snd_device == SND_DEVICE_OUT_TRANSMISSION_FM)
461 strlcat(mixer_path, " transmission-fm", MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700462}
463
464int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type)
465{
466 int device_id;
467 if (device_type == PCM_PLAYBACK)
468 device_id = pcm_device_table[usecase][0];
469 else
470 device_id = pcm_device_table[usecase][1];
471 return device_id;
472}
473
474int platform_send_audio_calibration(void *platform, snd_device_t snd_device)
475{
476 struct platform_data *my_data = (struct platform_data *)platform;
477 int acdb_dev_id, acdb_dev_type;
478
479 acdb_dev_id = acdb_device_table[snd_device];
480 if (acdb_dev_id < 0) {
481 ALOGE("%s: Could not find acdb id for device(%d)",
482 __func__, snd_device);
483 return -EINVAL;
484 }
485 if (my_data->acdb_send_audio_cal) {
Eric Laurent994a6932013-07-17 11:51:42 -0700486 ("%s: sending audio calibration for snd_device(%d) acdb_id(%d)",
Eric Laurentb23d5282013-05-14 15:27:20 -0700487 __func__, snd_device, acdb_dev_id);
488 if (snd_device >= SND_DEVICE_OUT_BEGIN &&
489 snd_device < SND_DEVICE_OUT_END)
490 acdb_dev_type = ACDB_DEV_TYPE_OUT;
491 else
492 acdb_dev_type = ACDB_DEV_TYPE_IN;
493 my_data->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type);
494 }
495 return 0;
496}
497
498int platform_switch_voice_call_device_pre(void *platform)
499{
500 return 0;
501}
502
503int platform_switch_voice_call_device_post(void *platform,
504 snd_device_t out_snd_device,
505 snd_device_t in_snd_device)
506{
507 struct platform_data *my_data = (struct platform_data *)platform;
508 int acdb_rx_id, acdb_tx_id;
509
510 if (my_data->acdb_send_voice_cal == NULL) {
511 ALOGE("%s: dlsym error for acdb_send_voice_call", __func__);
512 } else {
513 acdb_rx_id = acdb_device_table[out_snd_device];
514 acdb_tx_id = acdb_device_table[in_snd_device];
515
516 if (acdb_rx_id > 0 && acdb_tx_id > 0)
517 my_data->acdb_send_voice_cal(acdb_rx_id, acdb_tx_id);
518 else
519 ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__,
520 acdb_rx_id, acdb_tx_id);
521 }
522
523 return 0;
524}
525
526int platform_start_voice_call(void *platform)
527{
528 return 0;
529}
530
531int platform_stop_voice_call(void *platform)
532{
533 return 0;
534}
535
536int platform_set_voice_volume(void *platform, int volume)
537{
538 struct platform_data *my_data = (struct platform_data *)platform;
539 struct audio_device *adev = my_data->adev;
540 struct mixer_ctl *ctl;
sangwoo53b2cf02013-07-25 19:18:44 -0700541 const char *mixer_ctl_name = "Voice Rx Gain";
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700542 int vol_index = 0;
543 uint32_t set_values[ ] = {0,
544 ALL_SESSION_VSID,
545 DEFAULT_VOLUME_RAMP_DURATION_MS};
Eric Laurentb23d5282013-05-14 15:27:20 -0700546
547 // Voice volume levels are mapped to adsp volume levels as follows.
548 // 100 -> 5, 80 -> 4, 60 -> 3, 40 -> 2, 20 -> 1 0 -> 0
549 // But this values don't changed in kernel. So, below change is need.
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700550 vol_index = (int)percent_to_index(volume, MIN_VOL_INDEX, MAX_VOL_INDEX);
551 set_values[0] = vol_index;
Eric Laurentb23d5282013-05-14 15:27:20 -0700552
553 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
554 if (!ctl) {
555 ALOGE("%s: Could not get ctl for mixer cmd - %s",
556 __func__, mixer_ctl_name);
557 return -EINVAL;
558 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700559 ALOGV("Setting voice volume index: %d", set_values[0]);
560 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
Eric Laurentb23d5282013-05-14 15:27:20 -0700561
562 return 0;
563}
564
565int platform_set_mic_mute(void *platform, bool state)
566{
567 struct platform_data *my_data = (struct platform_data *)platform;
568 struct audio_device *adev = my_data->adev;
569 struct mixer_ctl *ctl;
570 const char *mixer_ctl_name = "Voice Tx Mute";
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700571 uint32_t set_values[ ] = {0,
572 ALL_SESSION_VSID,
573 DEFAULT_VOLUME_RAMP_DURATION_MS};
Eric Laurentb23d5282013-05-14 15:27:20 -0700574
575 if (adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700576 set_values[0] = state;
Eric Laurentb23d5282013-05-14 15:27:20 -0700577 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
578 if (!ctl) {
579 ALOGE("%s: Could not get ctl for mixer cmd - %s",
580 __func__, mixer_ctl_name);
581 return -EINVAL;
582 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700583 ALOGV("Setting voice mute state: %d", state);
584 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
Eric Laurentb23d5282013-05-14 15:27:20 -0700585 }
586
587 return 0;
588}
589
590snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices)
591{
592 struct platform_data *my_data = (struct platform_data *)platform;
593 struct audio_device *adev = my_data->adev;
594 audio_mode_t mode = adev->mode;
595 snd_device_t snd_device = SND_DEVICE_NONE;
596
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700597 audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
598 AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
599 int channel_count = popcount(channel_mask);
600
Eric Laurentb23d5282013-05-14 15:27:20 -0700601 ALOGV("%s: enter: output devices(%#x)", __func__, devices);
602 if (devices == AUDIO_DEVICE_NONE ||
603 devices & AUDIO_DEVICE_BIT_IN) {
604 ALOGV("%s: Invalid output devices (%#x)", __func__, devices);
605 goto exit;
606 }
607
608 if (mode == AUDIO_MODE_IN_CALL) {
609 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
610 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700611 if (adev->voice.tty_mode == TTY_MODE_FULL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700612 snd_device = SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES;
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700613 } else if (adev->voice.tty_mode == TTY_MODE_VCO) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700614 snd_device = SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES;
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700615 } else if (adev->voice.tty_mode == TTY_MODE_HCO) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700616 snd_device = SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET;
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700617 } else if (audio_extn_get_anc_enabled()) {
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700618 if (audio_extn_should_use_fb_anc())
619 snd_device = SND_DEVICE_OUT_VOICE_ANC_FB_HEADSET;
620 else
621 snd_device = SND_DEVICE_OUT_VOICE_ANC_HEADSET;
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700622 } else {
Eric Laurentb23d5282013-05-14 15:27:20 -0700623 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES;
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700624 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700625 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700626 if (my_data->btsco_sample_rate == SAMPLE_RATE_16KHZ)
627 snd_device = SND_DEVICE_OUT_BT_SCO_WB;
628 else
629 snd_device = SND_DEVICE_OUT_BT_SCO;
Eric Laurentb23d5282013-05-14 15:27:20 -0700630 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
631 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700632 } else if (devices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
633 devices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) {
634 snd_device = SND_DEVICE_OUT_USB_HEADSET;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700635 } else if (devices & AUDIO_DEVICE_OUT_FM_TX) {
636 snd_device = SND_DEVICE_OUT_TRANSMISSION_FM;
Eric Laurentb23d5282013-05-14 15:27:20 -0700637 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
638 if (is_operator_tmus())
639 snd_device = SND_DEVICE_OUT_VOICE_HANDSET_TMUS;
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700640 else if (audio_extn_should_use_handset_anc(channel_count))
641 snd_device = SND_DEVICE_OUT_ANC_HANDSET;
Eric Laurentb23d5282013-05-14 15:27:20 -0700642 else
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700643 snd_device = SND_DEVICE_OUT_VOICE_HANDSET;
Eric Laurentb23d5282013-05-14 15:27:20 -0700644 }
645 if (snd_device != SND_DEVICE_NONE) {
646 goto exit;
647 }
648 }
649
650 if (popcount(devices) == 2) {
651 if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
652 AUDIO_DEVICE_OUT_SPEAKER)) {
653 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
654 } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
655 AUDIO_DEVICE_OUT_SPEAKER)) {
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700656 if (audio_extn_get_anc_enabled())
657 snd_device = SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET;
658 else
659 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
Eric Laurentb23d5282013-05-14 15:27:20 -0700660 } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL |
661 AUDIO_DEVICE_OUT_SPEAKER)) {
662 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700663 } else if (devices == (AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
664 AUDIO_DEVICE_OUT_SPEAKER)) {
665 snd_device = SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET;
Eric Laurentb23d5282013-05-14 15:27:20 -0700666 } else {
667 ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
668 goto exit;
669 }
670 if (snd_device != SND_DEVICE_NONE) {
671 goto exit;
672 }
673 }
674
675 if (popcount(devices) != 1) {
676 ALOGE("%s: Invalid output devices(%#x)", __func__, devices);
677 goto exit;
678 }
679
680 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
681 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700682 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADSET
683 && audio_extn_get_anc_enabled()) {
684 if (audio_extn_should_use_fb_anc())
685 snd_device = SND_DEVICE_OUT_ANC_FB_HEADSET;
686 else
687 snd_device = SND_DEVICE_OUT_ANC_HEADSET;
688 }
689 else
690 snd_device = SND_DEVICE_OUT_HEADPHONES;
Eric Laurentb23d5282013-05-14 15:27:20 -0700691 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
692 if (adev->speaker_lr_swap)
693 snd_device = SND_DEVICE_OUT_SPEAKER_REVERSE;
694 else
695 snd_device = SND_DEVICE_OUT_SPEAKER;
696 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700697 if (my_data->btsco_sample_rate == SAMPLE_RATE_16KHZ)
698 snd_device = SND_DEVICE_OUT_BT_SCO_WB;
699 else
700 snd_device = SND_DEVICE_OUT_BT_SCO;
Eric Laurentb23d5282013-05-14 15:27:20 -0700701 } else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
702 snd_device = SND_DEVICE_OUT_HDMI ;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700703 } else if (devices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
704 devices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) {
705 snd_device = SND_DEVICE_OUT_USB_HEADSET;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700706 } else if (devices & AUDIO_DEVICE_OUT_FM_TX) {
707 snd_device = SND_DEVICE_OUT_TRANSMISSION_FM;
Eric Laurentb23d5282013-05-14 15:27:20 -0700708 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
709 snd_device = SND_DEVICE_OUT_HANDSET;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700710 } else if (devices & AUDIO_DEVICE_OUT_PROXY) {
711 ALOGD("%s: setting sink capability for Proxy", __func__);
712 audio_extn_set_afe_proxy_channel_mixer(adev);
713 snd_device = SND_DEVICE_OUT_AFE_PROXY;
Eric Laurentb23d5282013-05-14 15:27:20 -0700714 } else {
715 ALOGE("%s: Unknown device(s) %#x", __func__, devices);
716 }
717exit:
718 ALOGV("%s: exit: snd_device(%s)", __func__, device_table[snd_device]);
719 return snd_device;
720}
721
722snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device)
723{
724 struct platform_data *my_data = (struct platform_data *)platform;
725 struct audio_device *adev = my_data->adev;
726 audio_source_t source = (adev->active_input == NULL) ?
727 AUDIO_SOURCE_DEFAULT : adev->active_input->source;
728
729 audio_mode_t mode = adev->mode;
730 audio_devices_t in_device = ((adev->active_input == NULL) ?
731 AUDIO_DEVICE_NONE : adev->active_input->device)
732 & ~AUDIO_DEVICE_BIT_IN;
733 audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
734 AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
735 snd_device_t snd_device = SND_DEVICE_NONE;
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700736 int channel_count = popcount(channel_mask);
Eric Laurentb23d5282013-05-14 15:27:20 -0700737
738 ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
739 __func__, out_device, in_device);
740 if (mode == AUDIO_MODE_IN_CALL) {
741 if (out_device == AUDIO_DEVICE_NONE) {
742 ALOGE("%s: No output device set for voice call", __func__);
743 goto exit;
744 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700745 if (adev->voice.tty_mode != TTY_MODE_OFF) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700746 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
747 out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700748 switch (adev->voice.tty_mode) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700749 case TTY_MODE_FULL:
750 snd_device = SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC;
751 break;
752 case TTY_MODE_VCO:
753 snd_device = SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC;
754 break;
755 case TTY_MODE_HCO:
756 snd_device = SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC;
757 break;
758 default:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700759 ALOGE("%s: Invalid TTY mode (%#x)",
760 __func__, adev->voice.tty_mode);
Eric Laurentb23d5282013-05-14 15:27:20 -0700761 }
762 goto exit;
763 }
764 }
765 if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
766 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -0700767 if (out_device & AUDIO_DEVICE_OUT_EARPIECE &&
768 audio_extn_should_use_handset_anc(channel_count)) {
769 snd_device = SND_DEVICE_IN_AANC_HANDSET_MIC;
770 } else if (my_data->fluence_type == FLUENCE_NONE ||
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700771 my_data->fluence_in_voice_call == false) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700772 snd_device = SND_DEVICE_IN_HANDSET_MIC;
773 } else {
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700774 if (is_operator_tmus())
775 snd_device = SND_DEVICE_IN_VOICE_DMIC_TMUS;
Eric Laurentb23d5282013-05-14 15:27:20 -0700776 else
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700777 snd_device = SND_DEVICE_IN_VOICE_DMIC;
778 adev->acdb_settings |= DMIC_FLAG;
Eric Laurentb23d5282013-05-14 15:27:20 -0700779 }
780 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
781 snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
782 } else if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700783 if (my_data->btsco_sample_rate == SAMPLE_RATE_16KHZ)
784 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
785 else
786 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
Eric Laurentb23d5282013-05-14 15:27:20 -0700787 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700788 if (my_data->fluence_type != FLUENCE_NONE &&
789 my_data->fluence_in_voice_call &&
790 my_data->fluence_in_spkr_mode) {
791 if(my_data->fluence_type == FLUENCE_DUAL_MIC) {
792 adev->acdb_settings |= DMIC_FLAG;
793 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC;
794 } else {
795 adev->acdb_settings |= QMIC_FLAG;
796 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_QMIC;
797 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700798 } else {
799 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
800 }
801 }
802 } else if (source == AUDIO_SOURCE_CAMCORDER) {
803 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
804 in_device & AUDIO_DEVICE_IN_BACK_MIC) {
805 snd_device = SND_DEVICE_IN_CAMCORDER_MIC;
806 }
807 } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) {
808 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700809 if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
810 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC;
811 else if (my_data->fluence_in_voice_rec)
812 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE;
Eric Laurentb23d5282013-05-14 15:27:20 -0700813
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700814 if (snd_device == SND_DEVICE_NONE)
Eric Laurentb23d5282013-05-14 15:27:20 -0700815 snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
Mingming Yin8e5a4f62013-10-07 15:23:41 -0700816 else
817 adev->acdb_settings |= DMIC_FLAG;
Eric Laurentb23d5282013-05-14 15:27:20 -0700818 }
819 } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
820 if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
821 in_device = AUDIO_DEVICE_IN_BACK_MIC;
822 if (adev->active_input) {
823 if (adev->active_input->enable_aec) {
824 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
825 snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
826 } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
827 snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
828 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
829 snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
830 }
831 set_echo_reference(adev->mixer, "SLIM_RX");
832 } else
833 set_echo_reference(adev->mixer, "NONE");
834 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700835 } else if (source == AUDIO_SOURCE_FM_RX) {
836 if (in_device & AUDIO_DEVICE_IN_FM_RX) {
837 snd_device = SND_DEVICE_IN_CAPTURE_FM;
838 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700839 } else if (source == AUDIO_SOURCE_DEFAULT) {
840 goto exit;
841 }
842
843
844 if (snd_device != SND_DEVICE_NONE) {
845 goto exit;
846 }
847
848 if (in_device != AUDIO_DEVICE_NONE &&
849 !(in_device & AUDIO_DEVICE_IN_VOICE_CALL) &&
850 !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) {
851 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -0700852 if (audio_extn_ssr_get_enabled() && channel_count == 6)
853 snd_device = SND_DEVICE_IN_QUAD_MIC;
Apoorv Raghuvanshi6bd8dbf2013-10-19 18:37:52 -0700854 else if (channel_count > 1)
855 snd_device = SND_DEVICE_IN_HANDSET_STEREO_DMIC;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -0700856 else
857 snd_device = SND_DEVICE_IN_HANDSET_MIC;
Eric Laurentb23d5282013-05-14 15:27:20 -0700858 } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
859 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
860 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
861 snd_device = SND_DEVICE_IN_HEADSET_MIC;
862 } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700863 if (my_data->btsco_sample_rate == SAMPLE_RATE_16KHZ)
864 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
865 else
866 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
Eric Laurentb23d5282013-05-14 15:27:20 -0700867 } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) {
868 snd_device = SND_DEVICE_IN_HDMI_MIC;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700869 } else if (in_device & AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET ||
870 in_device & AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET) {
871 snd_device = SND_DEVICE_IN_USB_HEADSET_MIC;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700872 } else if (in_device & AUDIO_DEVICE_IN_FM_RX) {
873 snd_device = SND_DEVICE_IN_CAPTURE_FM;
Eric Laurentb23d5282013-05-14 15:27:20 -0700874 } else {
875 ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
876 ALOGW("%s: Using default handset-mic", __func__);
877 snd_device = SND_DEVICE_IN_HANDSET_MIC;
878 }
879 } else {
880 if (out_device & AUDIO_DEVICE_OUT_EARPIECE) {
881 snd_device = SND_DEVICE_IN_HANDSET_MIC;
882 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
883 snd_device = SND_DEVICE_IN_HEADSET_MIC;
884 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
Apoorv Raghuvanshi6bd8dbf2013-10-19 18:37:52 -0700885 if (channel_count > 1)
886 snd_device = SND_DEVICE_IN_SPEAKER_STEREO_DMIC;
887 else
888 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
Eric Laurentb23d5282013-05-14 15:27:20 -0700889 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
890 snd_device = SND_DEVICE_IN_HANDSET_MIC;
891 } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700892 if (my_data->btsco_sample_rate == SAMPLE_RATE_16KHZ)
893 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
894 else
895 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
Eric Laurentb23d5282013-05-14 15:27:20 -0700896 } else if (out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
897 snd_device = SND_DEVICE_IN_HDMI_MIC;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700898 } else if (out_device & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
899 out_device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) {
900 snd_device = SND_DEVICE_IN_USB_HEADSET_MIC;
Eric Laurentb23d5282013-05-14 15:27:20 -0700901 } else {
902 ALOGE("%s: Unknown output device(s) %#x", __func__, out_device);
903 ALOGW("%s: Using default handset-mic", __func__);
904 snd_device = SND_DEVICE_IN_HANDSET_MIC;
905 }
906 }
907exit:
908 ALOGV("%s: exit: in_snd_device(%s)", __func__, device_table[snd_device]);
909 return snd_device;
910}
911
912int platform_set_hdmi_channels(void *platform, int channel_count)
913{
914 struct platform_data *my_data = (struct platform_data *)platform;
915 struct audio_device *adev = my_data->adev;
916 struct mixer_ctl *ctl;
917 const char *channel_cnt_str = NULL;
918 const char *mixer_ctl_name = "HDMI_RX Channels";
919 switch (channel_count) {
920 case 8:
921 channel_cnt_str = "Eight"; break;
922 case 7:
923 channel_cnt_str = "Seven"; break;
924 case 6:
925 channel_cnt_str = "Six"; break;
926 case 5:
927 channel_cnt_str = "Five"; break;
928 case 4:
929 channel_cnt_str = "Four"; break;
930 case 3:
931 channel_cnt_str = "Three"; break;
932 default:
933 channel_cnt_str = "Two"; break;
934 }
935 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
936 if (!ctl) {
937 ALOGE("%s: Could not get ctl for mixer cmd - %s",
938 __func__, mixer_ctl_name);
939 return -EINVAL;
940 }
941 ALOGV("HDMI channel count: %s", channel_cnt_str);
942 mixer_ctl_set_enum_by_string(ctl, channel_cnt_str);
943 return 0;
944}
945
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700946int platform_edid_get_max_channels(void *platform)
Eric Laurentb23d5282013-05-14 15:27:20 -0700947{
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700948 struct platform_data *my_data = (struct platform_data *)platform;
949 struct audio_device *adev = my_data->adev;
Eric Laurentb23d5282013-05-14 15:27:20 -0700950 char block[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE];
951 char *sad = block;
952 int num_audio_blocks;
953 int channel_count;
954 int max_channels = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700955 int i, ret, count;
Eric Laurentb23d5282013-05-14 15:27:20 -0700956
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700957 struct mixer_ctl *ctl;
958
959 ctl = mixer_get_ctl_by_name(adev->mixer, AUDIO_DATA_BLOCK_MIXER_CTL);
960 if (!ctl) {
961 ALOGE("%s: Could not get ctl for mixer cmd - %s",
962 __func__, AUDIO_DATA_BLOCK_MIXER_CTL);
Eric Laurentb23d5282013-05-14 15:27:20 -0700963 return 0;
964 }
965
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700966 mixer_ctl_update(ctl);
967
968 count = mixer_ctl_get_num_values(ctl);
Eric Laurentb23d5282013-05-14 15:27:20 -0700969
970 /* Read SAD blocks, clamping the maximum size for safety */
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700971 if (count > (int)sizeof(block))
972 count = (int)sizeof(block);
Eric Laurentb23d5282013-05-14 15:27:20 -0700973
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700974 ret = mixer_ctl_get_array(ctl, block, count);
975 if (ret != 0) {
976 ALOGE("%s: mixer_ctl_get_array() failed to get EDID info", __func__);
977 return 0;
978 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700979
980 /* Calculate the number of SAD blocks */
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700981 num_audio_blocks = count / SAD_BLOCK_SIZE;
Eric Laurentb23d5282013-05-14 15:27:20 -0700982
983 for (i = 0; i < num_audio_blocks; i++) {
984 /* Only consider LPCM blocks */
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700985 if ((sad[0] >> 3) != EDID_FORMAT_LPCM) {
986 sad += 3;
Eric Laurentb23d5282013-05-14 15:27:20 -0700987 continue;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700988 }
Eric Laurentb23d5282013-05-14 15:27:20 -0700989
990 channel_count = (sad[0] & 0x7) + 1;
991 if (channel_count > max_channels)
992 max_channels = channel_count;
993
994 /* Advance to next block */
995 sad += 3;
996 }
997
998 return max_channels;
999}
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001000
1001static int platform_set_slowtalk(struct platform_data *my_data, bool state)
1002{
1003 int ret = 0;
1004 struct audio_device *adev = my_data->adev;
1005 struct mixer_ctl *ctl;
1006 const char *mixer_ctl_name = "Slowtalk Enable";
1007 uint32_t set_values[ ] = {0,
1008 ALL_SESSION_VSID};
1009
1010 set_values[0] = state;
1011 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1012 if (!ctl) {
1013 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1014 __func__, mixer_ctl_name);
1015 ret = -EINVAL;
1016 } else {
1017 ALOGV("Setting slowtalk state: %d", state);
1018 ret = mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1019 my_data->slowtalk = state;
1020 }
1021
1022 return ret;
1023}
1024
1025int platform_set_parameters(void *platform, struct str_parms *parms)
1026{
1027 struct platform_data *my_data = (struct platform_data *)platform;
1028 char *str;
1029 char value[32];
1030 int val;
1031 int ret = 0;
1032
1033 ALOGV("%s: enter: %s", __func__, str_parms_to_str(parms));
1034
1035 ret = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_BTSCO, &val);
1036 if (ret >= 0) {
1037 str_parms_del(parms, AUDIO_PARAMETER_KEY_BTSCO);
1038 pthread_mutex_lock(&my_data->adev->lock);
1039 my_data->btsco_sample_rate = val;
1040 pthread_mutex_unlock(&my_data->adev->lock);
1041 }
1042
1043 ret = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_SLOWTALK, &val);
1044 if (ret >= 0) {
1045 str_parms_del(parms, AUDIO_PARAMETER_KEY_SLOWTALK);
1046 pthread_mutex_lock(&my_data->adev->lock);
1047 ret = platform_set_slowtalk(my_data, val);
1048 if (ret)
1049 ALOGE("%s: Failed to set slow talk err: %d", __func__, ret);
1050 pthread_mutex_unlock(&my_data->adev->lock);
1051 }
1052
1053 ALOGV("%s: exit with code(%d)", __func__, ret);
1054 return ret;
1055}
1056
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001057int platform_set_incall_recoding_session_id(void *platform,
1058 uint32_t session_id)
1059{
1060 int ret = 0;
1061 struct platform_data *my_data = (struct platform_data *)platform;
1062 struct audio_device *adev = my_data->adev;
1063 struct mixer_ctl *ctl;
1064 const char *mixer_ctl_name = "Voc VSID";
1065 int num_ctl_values;
1066 int i;
1067
1068 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1069 if (!ctl) {
1070 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1071 __func__, mixer_ctl_name);
1072 ret = -EINVAL;
1073 } else {
1074 num_ctl_values = mixer_ctl_get_num_values(ctl);
1075 for (i = 0; i < num_ctl_values; i++) {
1076 if (mixer_ctl_set_value(ctl, i, session_id)) {
1077 ALOGV("Error: invalid session_id: %x", session_id);
1078 ret = -EINVAL;
1079 break;
1080 }
1081 }
1082 }
1083
1084 return ret;
1085}
1086
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001087void platform_get_parameters(void *platform,
1088 struct str_parms *query,
1089 struct str_parms *reply)
1090{
1091 struct platform_data *my_data = (struct platform_data *)platform;
1092 char *str = NULL;
1093 char value[256] = {0};
1094 int ret;
1095 int fluence_type;
1096
1097 ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_FLUENCE_TYPE,
1098 value, sizeof(value));
1099 if (ret >= 0) {
1100 pthread_mutex_lock(&my_data->adev->lock);
1101 if (my_data->fluence_type == FLUENCE_QUAD_MIC) {
1102 strlcpy(value, "fluencepro", sizeof(value));
1103 } else if (my_data->fluence_type == FLUENCE_DUAL_MIC) {
1104 strlcpy(value, "fluence", sizeof(value));
1105 } else {
1106 strlcpy(value, "none", sizeof(value));
1107 }
1108 pthread_mutex_unlock(&my_data->adev->lock);
1109
1110 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_FLUENCE_TYPE, value);
1111 }
1112
1113 ALOGV("%s: exit: returns - %s", __func__, str_parms_to_str(reply));
1114}
1115
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07001116/* Delay in Us */
1117int64_t platform_render_latency(audio_usecase_t usecase)
1118{
1119 switch (usecase) {
1120 case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER:
1121 return DEEP_BUFFER_PLATFORM_DELAY;
1122 case USECASE_AUDIO_PLAYBACK_LOW_LATENCY:
1123 return LOW_LATENCY_PLATFORM_DELAY;
1124 default:
1125 return 0;
1126 }
1127}