• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "msm8974_platform"
18 /*#define LOG_NDEBUG 0*/
19 #define LOG_NDDEBUG 0
20 
21 #include <stdlib.h>
22 #include <dlfcn.h>
23 #include <cutils/log.h>
24 #include <cutils/properties.h>
25 #include <audio_hw.h>
26 #include <platform_api.h>
27 #include "platform.h"
28 
29 #define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
30 #define LIB_ACDB_LOADER "libacdbloader.so"
31 #define AUDIO_DATA_BLOCK_MIXER_CTL "HDMI EDID"
32 
33 #define DUALMIC_CONFIG_NONE 0      /* Target does not contain 2 mics */
34 #define DUALMIC_CONFIG_ENDFIRE 1
35 #define DUALMIC_CONFIG_BROADSIDE 2
36 
37 /*
38  * This file will have a maximum of 38 bytes:
39  *
40  * 4 bytes: number of audio blocks
41  * 4 bytes: total length of Short Audio Descriptor (SAD) blocks
42  * Maximum 10 * 3 bytes: SAD blocks
43  */
44 #define MAX_SAD_BLOCKS      10
45 #define SAD_BLOCK_SIZE      3
46 
47 /* EDID format ID for LPCM audio */
48 #define EDID_FORMAT_LPCM    1
49 
50 /* Retry for delay in FW loading*/
51 #define RETRY_NUMBER 10
52 #define RETRY_US 500000
53 
54 #define MAX_VOL_INDEX 5
55 #define MIN_VOL_INDEX 0
56 #define percent_to_index(val, min, max) \
57 	        ((val) * ((max) - (min)) * 0.01 + (min) + .5)
58 
59 struct audio_block_header
60 {
61     int reserved;
62     int length;
63 };
64 
65 typedef void (*acdb_deallocate_t)();
66 typedef int  (*acdb_init_t)();
67 typedef void (*acdb_send_audio_cal_t)(int, int);
68 typedef void (*acdb_send_voice_cal_t)(int, int);
69 
70 /* Audio calibration related functions */
71 struct platform_data {
72     struct audio_device *adev;
73     bool fluence_in_spkr_mode;
74     bool fluence_in_voice_call;
75     bool fluence_in_voice_rec;
76     int  dualmic_config;
77 
78     void *acdb_handle;
79     acdb_init_t acdb_init;
80     acdb_deallocate_t acdb_deallocate;
81     acdb_send_audio_cal_t acdb_send_audio_cal;
82     acdb_send_voice_cal_t acdb_send_voice_cal;
83 };
84 
85 static const int pcm_device_table[AUDIO_USECASE_MAX][2] = {
86     [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
87     [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
88     [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
89     [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
90     [USECASE_AUDIO_RECORD] = {0, 0},
91     [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
92     [USECASE_VOICE_CALL] = {2, 2},
93 };
94 
95 /* Array to store sound devices */
96 static const char * const device_table[SND_DEVICE_MAX] = {
97     [SND_DEVICE_NONE] = "none",
98     /* Playback sound devices */
99     [SND_DEVICE_OUT_HANDSET] = "handset",
100     [SND_DEVICE_OUT_SPEAKER] = "speaker",
101     [SND_DEVICE_OUT_SPEAKER_REVERSE] = "speaker-reverse",
102     [SND_DEVICE_OUT_HEADPHONES] = "headphones",
103     [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones",
104     [SND_DEVICE_OUT_VOICE_HANDSET] = "voice-handset",
105     [SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker",
106     [SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones",
107     [SND_DEVICE_OUT_HDMI] = "hdmi",
108     [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
109     [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
110     [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = "voice-handset-tmus",
111     [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = "voice-tty-full-headphones",
112     [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = "voice-tty-vco-headphones",
113     [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = "voice-tty-hco-handset",
114 
115     /* Capture sound devices */
116     [SND_DEVICE_IN_HANDSET_MIC] = "handset-mic",
117     [SND_DEVICE_IN_SPEAKER_MIC] = "speaker-mic",
118     [SND_DEVICE_IN_HEADSET_MIC] = "headset-mic",
119     [SND_DEVICE_IN_HANDSET_MIC_AEC] = "handset-mic",
120     [SND_DEVICE_IN_SPEAKER_MIC_AEC] = "speaker-mic-aec",
121     [SND_DEVICE_IN_HEADSET_MIC_AEC] = "headset-mic",
122     [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "voice-speaker-mic",
123     [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "voice-headset-mic",
124     [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic",
125     [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic",
126     [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic",
127     [SND_DEVICE_IN_VOICE_DMIC_EF] = "voice-dmic-ef",
128     [SND_DEVICE_IN_VOICE_DMIC_BS] = "voice-dmic-bs",
129     [SND_DEVICE_IN_VOICE_DMIC_EF_TMUS] = "voice-dmic-ef-tmus",
130     [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF] = "voice-speaker-dmic-ef",
131     [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS] = "voice-speaker-dmic-bs",
132     [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = "voice-tty-full-headset-mic",
133     [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = "voice-tty-vco-handset-mic",
134     [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = "voice-tty-hco-headset-mic",
135     [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic",
136     [SND_DEVICE_IN_VOICE_REC_DMIC_EF] = "voice-rec-dmic-ef",
137     [SND_DEVICE_IN_VOICE_REC_DMIC_BS] = "voice-rec-dmic-bs",
138     [SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE] = "voice-rec-dmic-ef-fluence",
139     [SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE] = "voice-rec-dmic-bs-fluence",
140 };
141 
142 /* ACDB IDs (audio DSP path configuration IDs) for each sound device */
143 static const int acdb_device_table[SND_DEVICE_MAX] = {
144     [SND_DEVICE_NONE] = -1,
145     [SND_DEVICE_OUT_HANDSET] = 7,
146     [SND_DEVICE_OUT_SPEAKER] = 15,
147     [SND_DEVICE_OUT_SPEAKER_REVERSE] = 15,
148     [SND_DEVICE_OUT_HEADPHONES] = 10,
149     [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = 10,
150     [SND_DEVICE_OUT_VOICE_HANDSET] = 7,
151     [SND_DEVICE_OUT_VOICE_SPEAKER] = 15,
152     [SND_DEVICE_OUT_VOICE_HEADPHONES] = 10,
153     [SND_DEVICE_OUT_HDMI] = 18,
154     [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 15,
155     [SND_DEVICE_OUT_BT_SCO] = 22,
156     [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = 88,
157     [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = 17,
158     [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = 17,
159     [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = 37,
160 
161     [SND_DEVICE_IN_HANDSET_MIC] = 4,
162     [SND_DEVICE_IN_SPEAKER_MIC] = 4, /* ToDo: Check if this needs to changed to 11 */
163     [SND_DEVICE_IN_HEADSET_MIC] = 8,
164     [SND_DEVICE_IN_HANDSET_MIC_AEC] = 40,
165     [SND_DEVICE_IN_SPEAKER_MIC_AEC] = 42,
166     [SND_DEVICE_IN_HEADSET_MIC_AEC] = 47,
167     [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = 11,
168     [SND_DEVICE_IN_VOICE_HEADSET_MIC] = 8,
169     [SND_DEVICE_IN_HDMI_MIC] = 4,
170     [SND_DEVICE_IN_BT_SCO_MIC] = 21,
171     [SND_DEVICE_IN_CAMCORDER_MIC] = 61,
172     [SND_DEVICE_IN_VOICE_DMIC_EF] = 41,
173     [SND_DEVICE_IN_VOICE_DMIC_BS] = 5,
174     [SND_DEVICE_IN_VOICE_DMIC_EF_TMUS] = 89,
175     [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF] = 43,
176     [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS] = 12,
177     [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = 16,
178     [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = 36,
179     [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = 16,
180     [SND_DEVICE_IN_VOICE_REC_MIC] = 62,
181     /* TODO: Update with proper acdb ids */
182     [SND_DEVICE_IN_VOICE_REC_DMIC_EF] = 62,
183     [SND_DEVICE_IN_VOICE_REC_DMIC_BS] = 62,
184     [SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE] = 6,
185     [SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE] = 5,
186 };
187 
188 #define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL)
189 #define LOW_LATENCY_PLATFORM_DELAY (13*1000LL)
190 
191 static pthread_once_t check_op_once_ctl = PTHREAD_ONCE_INIT;
192 static bool is_tmus = false;
193 
check_operator()194 static void check_operator()
195 {
196     char value[PROPERTY_VALUE_MAX];
197     int mccmnc;
198     property_get("gsm.sim.operator.numeric",value,"0");
199     mccmnc = atoi(value);
200     ALOGD("%s: tmus mccmnc %d", __func__, mccmnc);
201     switch(mccmnc) {
202     /* TMUS MCC(310), MNC(490, 260, 026) */
203     case 310490:
204     case 310260:
205     case 310026:
206     /* Add new TMUS MNC(800, 660, 580, 310, 270, 250, 240, 230, 220, 210, 200, 160) */
207     case 310800:
208     case 310660:
209     case 310580:
210     case 310310:
211     case 310270:
212     case 310250:
213     case 310240:
214     case 310230:
215     case 310220:
216     case 310210:
217     case 310200:
218     case 310160:
219         is_tmus = true;
220         break;
221     }
222 }
223 
is_operator_tmus()224 bool is_operator_tmus()
225 {
226     pthread_once(&check_op_once_ctl, check_operator);
227     return is_tmus;
228 }
229 
set_volume_values(int type,int volume,int * values)230 static int set_volume_values(int type, int volume, int* values)
231 {
232     values[0] = volume;
233     values[1] = ALL_SESSION_VSID;
234 
235     switch(type) {
236     case VOLUME_SET:
237         values[2] = DEFAULT_VOLUME_RAMP_DURATION_MS;
238         break;
239     case MUTE_SET:
240         values[2] = DEFAULT_MUTE_RAMP_DURATION;
241         break;
242     default:
243         return -EINVAL;
244     }
245     return 0;
246 }
247 
set_echo_reference(struct mixer * mixer,const char * ec_ref)248 static int set_echo_reference(struct mixer *mixer, const char* ec_ref)
249 {
250     struct mixer_ctl *ctl;
251     const char *mixer_ctl_name = "EC_REF_RX";
252 
253     ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
254     if (!ctl) {
255         ALOGE("%s: Could not get ctl for mixer cmd - %s",
256               __func__, mixer_ctl_name);
257         return -EINVAL;
258     }
259     ALOGV("Setting EC Reference: %s", ec_ref);
260     mixer_ctl_set_enum_by_string(ctl, ec_ref);
261     return 0;
262 }
263 
platform_init(struct audio_device * adev)264 void *platform_init(struct audio_device *adev)
265 {
266     char value[PROPERTY_VALUE_MAX];
267     struct platform_data *my_data;
268     int retry_num = 0;
269 
270     adev->mixer = mixer_open(MIXER_CARD);
271 
272     while (!adev->mixer && retry_num < RETRY_NUMBER) {
273         usleep(RETRY_US);
274         adev->mixer = mixer_open(MIXER_CARD);
275         retry_num++;
276     }
277 
278     if (!adev->mixer) {
279         ALOGE("Unable to open the mixer, aborting.");
280         return NULL;
281     }
282 
283     adev->audio_route = audio_route_init(MIXER_CARD, MIXER_XML_PATH);
284     if (!adev->audio_route) {
285         ALOGE("%s: Failed to init audio route controls, aborting.", __func__);
286         return NULL;
287     }
288 
289     my_data = calloc(1, sizeof(struct platform_data));
290 
291     my_data->adev = adev;
292     my_data->dualmic_config = DUALMIC_CONFIG_NONE;
293     my_data->fluence_in_spkr_mode = false;
294     my_data->fluence_in_voice_call = false;
295     my_data->fluence_in_voice_rec = false;
296 
297     property_get("persist.audio.dualmic.config",value,"");
298     if (!strcmp("broadside", value)) {
299         my_data->dualmic_config = DUALMIC_CONFIG_BROADSIDE;
300         adev->acdb_settings |= DMIC_FLAG;
301     } else if (!strcmp("endfire", value)) {
302         my_data->dualmic_config = DUALMIC_CONFIG_ENDFIRE;
303         adev->acdb_settings |= DMIC_FLAG;
304     }
305 
306     if (my_data->dualmic_config != DUALMIC_CONFIG_NONE) {
307         property_get("persist.audio.fluence.voicecall",value,"");
308         if (!strcmp("true", value)) {
309             my_data->fluence_in_voice_call = true;
310         }
311 
312         property_get("persist.audio.fluence.voicerec",value,"");
313         if (!strcmp("true", value)) {
314             my_data->fluence_in_voice_rec = true;
315         }
316 
317         property_get("persist.audio.fluence.speaker",value,"");
318         if (!strcmp("true", value)) {
319             my_data->fluence_in_spkr_mode = true;
320         }
321     }
322 
323     my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
324     if (my_data->acdb_handle == NULL) {
325         ALOGE("%s: DLOPEN failed for %s", __func__, LIB_ACDB_LOADER);
326     } else {
327         ALOGV("%s: DLOPEN successful for %s", __func__, LIB_ACDB_LOADER);
328         my_data->acdb_deallocate = (acdb_deallocate_t)dlsym(my_data->acdb_handle,
329                                                     "acdb_loader_deallocate_ACDB");
330         my_data->acdb_send_audio_cal = (acdb_send_audio_cal_t)dlsym(my_data->acdb_handle,
331                                                     "acdb_loader_send_audio_cal");
332         if (!my_data->acdb_send_audio_cal)
333             ALOGW("%s: Could not find the symbol acdb_send_audio_cal from %s",
334                   __func__, LIB_ACDB_LOADER);
335         my_data->acdb_send_voice_cal = (acdb_send_voice_cal_t)dlsym(my_data->acdb_handle,
336                                                     "acdb_loader_send_voice_cal");
337         my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
338                                                     "acdb_loader_init_ACDB");
339         if (my_data->acdb_init == NULL)
340             ALOGE("%s: dlsym error %s for acdb_loader_init_ACDB", __func__, dlerror());
341         else
342             my_data->acdb_init();
343     }
344 
345     return my_data;
346 }
347 
platform_deinit(void * platform)348 void platform_deinit(void *platform)
349 {
350     free(platform);
351 }
352 
platform_get_snd_device_name(snd_device_t snd_device)353 const char *platform_get_snd_device_name(snd_device_t snd_device)
354 {
355     if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX)
356         return device_table[snd_device];
357     else
358         return "";
359 }
360 
platform_add_backend_name(char * mixer_path,snd_device_t snd_device)361 void platform_add_backend_name(char *mixer_path, snd_device_t snd_device)
362 {
363     if (snd_device == SND_DEVICE_IN_BT_SCO_MIC)
364         strcat(mixer_path, " bt-sco");
365     else if(snd_device == SND_DEVICE_OUT_BT_SCO)
366         strcat(mixer_path, " bt-sco");
367     else if (snd_device == SND_DEVICE_OUT_HDMI)
368         strcat(mixer_path, " hdmi");
369     else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HDMI)
370         strcat(mixer_path, " speaker-and-hdmi");
371 }
372 
platform_get_pcm_device_id(audio_usecase_t usecase,int device_type)373 int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type)
374 {
375     int device_id;
376     if (device_type == PCM_PLAYBACK)
377         device_id = pcm_device_table[usecase][0];
378     else
379         device_id = pcm_device_table[usecase][1];
380     return device_id;
381 }
382 
platform_send_audio_calibration(void * platform,snd_device_t snd_device)383 int platform_send_audio_calibration(void *platform, snd_device_t snd_device)
384 {
385     struct platform_data *my_data = (struct platform_data *)platform;
386     int acdb_dev_id, acdb_dev_type;
387 
388     acdb_dev_id = acdb_device_table[snd_device];
389     if (acdb_dev_id < 0) {
390         ALOGE("%s: Could not find acdb id for device(%d)",
391               __func__, snd_device);
392         return -EINVAL;
393     }
394     if (my_data->acdb_send_audio_cal) {
395         ("%s: sending audio calibration for snd_device(%d) acdb_id(%d)",
396               __func__, snd_device, acdb_dev_id);
397         if (snd_device >= SND_DEVICE_OUT_BEGIN &&
398                 snd_device < SND_DEVICE_OUT_END)
399             acdb_dev_type = ACDB_DEV_TYPE_OUT;
400         else
401             acdb_dev_type = ACDB_DEV_TYPE_IN;
402         my_data->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type);
403     }
404     return 0;
405 }
406 
platform_switch_voice_call_device_pre(void * platform)407 int platform_switch_voice_call_device_pre(void *platform)
408 {
409     return 0;
410 }
411 
platform_switch_voice_call_device_post(void * platform,snd_device_t out_snd_device,snd_device_t in_snd_device)412 int platform_switch_voice_call_device_post(void *platform,
413                                            snd_device_t out_snd_device,
414                                            snd_device_t in_snd_device)
415 {
416     struct platform_data *my_data = (struct platform_data *)platform;
417     int acdb_rx_id, acdb_tx_id;
418 
419     if (my_data->acdb_send_voice_cal == NULL) {
420         ALOGE("%s: dlsym error for acdb_send_voice_call", __func__);
421     } else {
422         acdb_rx_id = acdb_device_table[out_snd_device];
423         acdb_tx_id = acdb_device_table[in_snd_device];
424 
425         if (acdb_rx_id > 0 && acdb_tx_id > 0)
426             my_data->acdb_send_voice_cal(acdb_rx_id, acdb_tx_id);
427         else
428             ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__,
429                   acdb_rx_id, acdb_tx_id);
430     }
431 
432     return 0;
433 }
434 
platform_start_voice_call(void * platform)435 int platform_start_voice_call(void *platform)
436 {
437     return 0;
438 }
439 
platform_stop_voice_call(void * platform)440 int platform_stop_voice_call(void *platform)
441 {
442     return 0;
443 }
444 
platform_set_voice_volume(void * platform,int volume)445 int platform_set_voice_volume(void *platform, int volume)
446 {
447     struct platform_data *my_data = (struct platform_data *)platform;
448     struct audio_device *adev = my_data->adev;
449     struct mixer_ctl *ctl;
450     const char *mixer_ctl_name = "Voice Rx Gain";
451     int values[VOLUME_CTL_PARAM_NUM];
452     int ret = 0;
453 
454     // Voice volume levels are mapped to adsp volume levels as follows.
455     // 100 -> 5, 80 -> 4, 60 -> 3, 40 -> 2, 20 -> 1  0 -> 0
456     // But this values don't changed in kernel. So, below change is need.
457     volume = (int)percent_to_index(volume, MIN_VOL_INDEX, MAX_VOL_INDEX);
458 
459     ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
460     if (!ctl) {
461         ALOGE("%s: Could not get ctl for mixer cmd - %s",
462               __func__, mixer_ctl_name);
463         return -EINVAL;
464     }
465     ret = set_volume_values(VOLUME_SET, volume, values);
466     if (ret < 0) {
467         ALOGV("%s: failed setting volume by incorrect type", __func__);
468         return -EINVAL;
469     }
470     ret = mixer_ctl_set_array(ctl, values, sizeof(values)/sizeof(int));
471     if (ret < 0) {
472         ALOGV("%s: failed set mixer ctl by %d", __func__, ret);
473         return -EINVAL;
474     }
475 
476     return 0;
477 }
478 
platform_set_mic_mute(void * platform,bool state)479 int platform_set_mic_mute(void *platform, bool state)
480 {
481     struct platform_data *my_data = (struct platform_data *)platform;
482     struct audio_device *adev = my_data->adev;
483     struct mixer_ctl *ctl;
484     const char *mixer_ctl_name = "Voice Tx Mute";
485     int values[VOLUME_CTL_PARAM_NUM];
486     int ret = 0;
487 
488     if (adev->mode == AUDIO_MODE_IN_CALL) {
489         ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
490         if (!ctl) {
491             ALOGE("%s: Could not get ctl for mixer cmd - %s",
492                   __func__, mixer_ctl_name);
493             return -EINVAL;
494         }
495         ALOGV("Setting mic mute: %d", state);
496         ret = set_volume_values(MUTE_SET, state, values);
497         if (ret < 0) {
498             ALOGV("%s: failed setting mute by incorrect type", __func__);
499             return -EINVAL;
500         }
501         ret = mixer_ctl_set_array(ctl, values, sizeof(values)/sizeof(int));
502         if (ret < 0) {
503             ALOGV("%s: failed set mixer ctl by %d", __func__, ret);
504             return -EINVAL;
505         }
506     }
507 
508     return 0;
509 }
510 
platform_get_output_snd_device(void * platform,audio_devices_t devices)511 snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices)
512 {
513     struct platform_data *my_data = (struct platform_data *)platform;
514     struct audio_device *adev = my_data->adev;
515     audio_mode_t mode = adev->mode;
516     snd_device_t snd_device = SND_DEVICE_NONE;
517 
518     ALOGV("%s: enter: output devices(%#x)", __func__, devices);
519     if (devices == AUDIO_DEVICE_NONE ||
520         devices & AUDIO_DEVICE_BIT_IN) {
521         ALOGV("%s: Invalid output devices (%#x)", __func__, devices);
522         goto exit;
523     }
524 
525     if (mode == AUDIO_MODE_IN_CALL) {
526         if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
527             devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
528             if (adev->tty_mode == TTY_MODE_FULL)
529                 snd_device = SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES;
530             else if (adev->tty_mode == TTY_MODE_VCO)
531                 snd_device = SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES;
532             else if (adev->tty_mode == TTY_MODE_HCO)
533                 snd_device = SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET;
534             else
535                 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES;
536         } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
537             snd_device = SND_DEVICE_OUT_BT_SCO;
538         } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
539             snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
540         } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
541             if (is_operator_tmus())
542                 snd_device = SND_DEVICE_OUT_VOICE_HANDSET_TMUS;
543             else
544                 snd_device = SND_DEVICE_OUT_HANDSET;
545         }
546         if (snd_device != SND_DEVICE_NONE) {
547             goto exit;
548         }
549     }
550 
551     if (popcount(devices) == 2) {
552         if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
553                         AUDIO_DEVICE_OUT_SPEAKER)) {
554             snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
555         } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
556                                AUDIO_DEVICE_OUT_SPEAKER)) {
557             snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
558         } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL |
559                                AUDIO_DEVICE_OUT_SPEAKER)) {
560             snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
561         } else {
562             ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
563             goto exit;
564         }
565         if (snd_device != SND_DEVICE_NONE) {
566             goto exit;
567         }
568     }
569 
570     if (popcount(devices) != 1) {
571         ALOGE("%s: Invalid output devices(%#x)", __func__, devices);
572         goto exit;
573     }
574 
575     if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
576         devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
577         snd_device = SND_DEVICE_OUT_HEADPHONES;
578     } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
579         if (adev->speaker_lr_swap)
580             snd_device = SND_DEVICE_OUT_SPEAKER_REVERSE;
581         else
582             snd_device = SND_DEVICE_OUT_SPEAKER;
583     } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
584         snd_device = SND_DEVICE_OUT_BT_SCO;
585     } else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
586         snd_device = SND_DEVICE_OUT_HDMI ;
587     } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
588         snd_device = SND_DEVICE_OUT_HANDSET;
589     } else {
590         ALOGE("%s: Unknown device(s) %#x", __func__, devices);
591     }
592 exit:
593     ALOGV("%s: exit: snd_device(%s)", __func__, device_table[snd_device]);
594     return snd_device;
595 }
596 
platform_get_input_snd_device(void * platform,audio_devices_t out_device)597 snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device)
598 {
599     struct platform_data *my_data = (struct platform_data *)platform;
600     struct audio_device *adev = my_data->adev;
601     audio_source_t  source = (adev->active_input == NULL) ?
602                                 AUDIO_SOURCE_DEFAULT : adev->active_input->source;
603 
604     audio_mode_t    mode   = adev->mode;
605     audio_devices_t in_device = ((adev->active_input == NULL) ?
606                                     AUDIO_DEVICE_NONE : adev->active_input->device)
607                                 & ~AUDIO_DEVICE_BIT_IN;
608     audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
609                                 AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
610     snd_device_t snd_device = SND_DEVICE_NONE;
611 
612     ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
613           __func__, out_device, in_device);
614     if (mode == AUDIO_MODE_IN_CALL) {
615         if (out_device == AUDIO_DEVICE_NONE) {
616             ALOGE("%s: No output device set for voice call", __func__);
617             goto exit;
618         }
619         if (adev->tty_mode != TTY_MODE_OFF) {
620             if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
621                 out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
622                 switch (adev->tty_mode) {
623                 case TTY_MODE_FULL:
624                     snd_device = SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC;
625                     break;
626                 case TTY_MODE_VCO:
627                     snd_device = SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC;
628                     break;
629                 case TTY_MODE_HCO:
630                     snd_device = SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC;
631                     break;
632                 default:
633                     ALOGE("%s: Invalid TTY mode (%#x)", __func__, adev->tty_mode);
634                 }
635                 goto exit;
636             }
637         }
638         if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
639             out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
640             if (my_data->fluence_in_voice_call == false) {
641                 snd_device = SND_DEVICE_IN_HANDSET_MIC;
642             } else {
643                 if (my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
644                     if (is_operator_tmus())
645                         snd_device = SND_DEVICE_IN_VOICE_DMIC_EF_TMUS;
646                     else
647                         snd_device = SND_DEVICE_IN_VOICE_DMIC_EF;
648                 } else if(my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE)
649                     snd_device = SND_DEVICE_IN_VOICE_DMIC_BS;
650                 else
651                     snd_device = SND_DEVICE_IN_HANDSET_MIC;
652             }
653         } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
654             snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
655         } else if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
656             snd_device = SND_DEVICE_IN_BT_SCO_MIC ;
657         } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
658             if (my_data->fluence_in_voice_call && my_data->fluence_in_spkr_mode &&
659                     my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
660                 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF;
661             } else if (my_data->fluence_in_voice_call && my_data->fluence_in_spkr_mode &&
662                     my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE) {
663                 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS;
664             } else {
665                 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
666             }
667         }
668     } else if (source == AUDIO_SOURCE_CAMCORDER) {
669         if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
670             in_device & AUDIO_DEVICE_IN_BACK_MIC) {
671             snd_device = SND_DEVICE_IN_CAMCORDER_MIC;
672         }
673     } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) {
674         if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
675             if (my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
676                 if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
677                     snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_EF;
678                 else if (my_data->fluence_in_voice_rec)
679                     snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE;
680             } else if (my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE) {
681                 if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
682                     snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_BS;
683                 else if (my_data->fluence_in_voice_rec)
684                     snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE;
685             }
686 
687             if (snd_device == SND_DEVICE_NONE) {
688                 snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
689             }
690         }
691     } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
692         if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
693             in_device = AUDIO_DEVICE_IN_BACK_MIC;
694         if (adev->active_input) {
695             if (adev->active_input->enable_aec) {
696                 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
697                     snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
698                 } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
699                     snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
700                 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
701                     snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
702                 }
703                 set_echo_reference(adev->mixer, "SLIM_RX");
704             } else
705                 set_echo_reference(adev->mixer, "NONE");
706         }
707     } else if (source == AUDIO_SOURCE_DEFAULT) {
708         goto exit;
709     }
710 
711 
712     if (snd_device != SND_DEVICE_NONE) {
713         goto exit;
714     }
715 
716     if (in_device != AUDIO_DEVICE_NONE &&
717             !(in_device & AUDIO_DEVICE_IN_VOICE_CALL) &&
718             !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) {
719         if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
720             snd_device = SND_DEVICE_IN_HANDSET_MIC;
721         } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
722             snd_device = SND_DEVICE_IN_SPEAKER_MIC;
723         } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
724             snd_device = SND_DEVICE_IN_HEADSET_MIC;
725         } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
726             snd_device = SND_DEVICE_IN_BT_SCO_MIC ;
727         } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) {
728             snd_device = SND_DEVICE_IN_HDMI_MIC;
729         } else {
730             ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
731             ALOGW("%s: Using default handset-mic", __func__);
732             snd_device = SND_DEVICE_IN_HANDSET_MIC;
733         }
734     } else {
735         if (out_device & AUDIO_DEVICE_OUT_EARPIECE) {
736             snd_device = SND_DEVICE_IN_HANDSET_MIC;
737         } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
738             snd_device = SND_DEVICE_IN_HEADSET_MIC;
739         } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
740             snd_device = SND_DEVICE_IN_SPEAKER_MIC;
741         } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
742             snd_device = SND_DEVICE_IN_HANDSET_MIC;
743         } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
744             snd_device = SND_DEVICE_IN_BT_SCO_MIC;
745         } else if (out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
746             snd_device = SND_DEVICE_IN_HDMI_MIC;
747         } else {
748             ALOGE("%s: Unknown output device(s) %#x", __func__, out_device);
749             ALOGW("%s: Using default handset-mic", __func__);
750             snd_device = SND_DEVICE_IN_HANDSET_MIC;
751         }
752     }
753 exit:
754     ALOGV("%s: exit: in_snd_device(%s)", __func__, device_table[snd_device]);
755     return snd_device;
756 }
757 
platform_set_hdmi_channels(void * platform,int channel_count)758 int platform_set_hdmi_channels(void *platform,  int channel_count)
759 {
760     struct platform_data *my_data = (struct platform_data *)platform;
761     struct audio_device *adev = my_data->adev;
762     struct mixer_ctl *ctl;
763     const char *channel_cnt_str = NULL;
764     const char *mixer_ctl_name = "HDMI_RX Channels";
765     switch (channel_count) {
766     case 8:
767         channel_cnt_str = "Eight"; break;
768     case 7:
769         channel_cnt_str = "Seven"; break;
770     case 6:
771         channel_cnt_str = "Six"; break;
772     case 5:
773         channel_cnt_str = "Five"; break;
774     case 4:
775         channel_cnt_str = "Four"; break;
776     case 3:
777         channel_cnt_str = "Three"; break;
778     default:
779         channel_cnt_str = "Two"; break;
780     }
781     ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
782     if (!ctl) {
783         ALOGE("%s: Could not get ctl for mixer cmd - %s",
784               __func__, mixer_ctl_name);
785         return -EINVAL;
786     }
787     ALOGV("HDMI channel count: %s", channel_cnt_str);
788     mixer_ctl_set_enum_by_string(ctl, channel_cnt_str);
789     return 0;
790 }
791 
platform_edid_get_max_channels(void * platform)792 int platform_edid_get_max_channels(void *platform)
793 {
794     struct platform_data *my_data = (struct platform_data *)platform;
795     struct audio_device *adev = my_data->adev;
796     char block[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE];
797     char *sad = block;
798     int num_audio_blocks;
799     int channel_count;
800     int max_channels = 0;
801     int i, ret, count;
802 
803     struct mixer_ctl *ctl;
804 
805     ctl = mixer_get_ctl_by_name(adev->mixer, AUDIO_DATA_BLOCK_MIXER_CTL);
806     if (!ctl) {
807         ALOGE("%s: Could not get ctl for mixer cmd - %s",
808               __func__, AUDIO_DATA_BLOCK_MIXER_CTL);
809         return 0;
810     }
811 
812     mixer_ctl_update(ctl);
813 
814     count = mixer_ctl_get_num_values(ctl);
815 
816     /* Read SAD blocks, clamping the maximum size for safety */
817     if (count > (int)sizeof(block))
818         count = (int)sizeof(block);
819 
820     ret = mixer_ctl_get_array(ctl, block, count);
821     if (ret != 0) {
822         ALOGE("%s: mixer_ctl_get_array() failed to get EDID info", __func__);
823         return 0;
824     }
825 
826     /* Calculate the number of SAD blocks */
827     num_audio_blocks = count / SAD_BLOCK_SIZE;
828 
829     for (i = 0; i < num_audio_blocks; i++) {
830         /* Only consider LPCM blocks */
831         if ((sad[0] >> 3) != EDID_FORMAT_LPCM) {
832             sad += 3;
833             continue;
834         }
835 
836         channel_count = (sad[0] & 0x7) + 1;
837         if (channel_count > max_channels)
838             max_channels = channel_count;
839 
840         /* Advance to next block */
841         sad += 3;
842     }
843 
844     return max_channels;
845 }
846 
847 /* Delay in Us */
platform_render_latency(audio_usecase_t usecase)848 int64_t platform_render_latency(audio_usecase_t usecase)
849 {
850     switch (usecase) {
851         case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER:
852             return DEEP_BUFFER_PLATFORM_DELAY;
853         case USECASE_AUDIO_PLAYBACK_LOW_LATENCY:
854             return LOW_LATENCY_PLATFORM_DELAY;
855         default:
856             return 0;
857     }
858 }
859