Home | History | Annotate | Download | only in msm8960
      1 /*
      2  * Copyright (C) 2013-2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "msm8960_platform"
     18 /*#define LOG_NDEBUG 0*/
     19 #define LOG_NDDEBUG 0
     20 
     21 #include <stdlib.h>
     22 #include <dlfcn.h>
     23 #include <log/log.h>
     24 #include <cutils/properties.h>
     25 #include <audio_hw.h>
     26 #include <platform_api.h>
     27 #include "platform.h"
     28 #include "audio_extn.h"
     29 
     30 #define LIB_ACDB_LOADER "libacdbloader.so"
     31 #define LIB_CSD_CLIENT "libcsd-client.so"
     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 is the sysfs path for the HDMI audio data block
     39  */
     40 #define AUDIO_DATA_BLOCK_PATH "/sys/class/graphics/fb1/audio_data_block"
     41 #define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
     42 
     43 /*
     44  * This file will have a maximum of 38 bytes:
     45  *
     46  * 4 bytes: number of audio blocks
     47  * 4 bytes: total length of Short Audio Descriptor (SAD) blocks
     48  * Maximum 10 * 3 bytes: SAD blocks
     49  */
     50 #define MAX_SAD_BLOCKS      10
     51 #define SAD_BLOCK_SIZE      3
     52 
     53 /* EDID format ID for LPCM audio */
     54 #define EDID_FORMAT_LPCM    1
     55 
     56 struct audio_block_header
     57 {
     58     int reserved;
     59     int length;
     60 };
     61 
     62 
     63 typedef void (*acdb_deallocate_t)();
     64 typedef int  (*acdb_init_t)();
     65 typedef void (*acdb_send_audio_cal_t)(int, int);
     66 typedef void (*acdb_send_voice_cal_t)(int, int);
     67 
     68 typedef int (*csd_client_init_t)();
     69 typedef int (*csd_client_deinit_t)();
     70 typedef int (*csd_disable_device_t)();
     71 typedef int (*csd_enable_device_t)(int, int, uint32_t);
     72 typedef int (*csd_volume_t)(int);
     73 typedef int (*csd_mic_mute_t)(int);
     74 typedef int (*csd_start_voice_t)();
     75 typedef int (*csd_stop_voice_t)();
     76 
     77 
     78 /* Audio calibration related functions */
     79 struct platform_data {
     80     struct audio_device *adev;
     81     bool fluence_in_spkr_mode;
     82     bool fluence_in_voice_call;
     83     bool fluence_in_voice_rec;
     84     int  dualmic_config;
     85     bool speaker_lr_swap;
     86 
     87     void *acdb_handle;
     88     acdb_init_t acdb_init;
     89     acdb_deallocate_t acdb_deallocate;
     90     acdb_send_audio_cal_t acdb_send_audio_cal;
     91     acdb_send_voice_cal_t acdb_send_voice_cal;
     92 
     93     /* CSD Client related functions for voice call */
     94     void *csd_client;
     95     csd_client_init_t csd_client_init;
     96     csd_client_deinit_t csd_client_deinit;
     97     csd_disable_device_t csd_disable_device;
     98     csd_enable_device_t csd_enable_device;
     99     csd_volume_t csd_volume;
    100     csd_mic_mute_t csd_mic_mute;
    101     csd_start_voice_t csd_start_voice;
    102     csd_stop_voice_t csd_stop_voice;
    103 };
    104 
    105 static const int pcm_device_table[AUDIO_USECASE_MAX][2] = {
    106     [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
    107     [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {14, 14},
    108     [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
    109     [USECASE_AUDIO_RECORD] = {0, 0},
    110     [USECASE_AUDIO_RECORD_LOW_LATENCY] = {14, 14},
    111     [USECASE_VOICE_CALL] = {12, 12},
    112 };
    113 
    114 /* Array to store sound devices */
    115 static const char * const device_table[SND_DEVICE_MAX] = {
    116     [SND_DEVICE_NONE] = "none",
    117     /* Playback sound devices */
    118     [SND_DEVICE_OUT_HANDSET] = "handset",
    119     [SND_DEVICE_OUT_SPEAKER] = "speaker",
    120     [SND_DEVICE_OUT_SPEAKER_REVERSE] = "speaker-reverse",
    121     [SND_DEVICE_OUT_SPEAKER_SAFE] = "speaker-safe",
    122     [SND_DEVICE_OUT_HEADPHONES] = "headphones",
    123     [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones",
    124     [SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker",
    125     [SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones",
    126     [SND_DEVICE_OUT_HDMI] = "hdmi",
    127     [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
    128     [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
    129     [SND_DEVICE_OUT_BT_SCO_WB] = "bt-sco-headset-wb",
    130     [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = "voice-handset-tmus",
    131     [SND_DEVICE_OUT_VOICE_HANDSET] = "voice-handset-tmus",
    132     [SND_DEVICE_OUT_VOICE_HAC_HANDSET] = "voice-handset-tmus",
    133     [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = "voice-tty-full-headphones",
    134     [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = "voice-tty-vco-headphones",
    135     [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = "voice-tty-hco-handset",
    136     [SND_DEVICE_OUT_USB_HEADSET] = "usb-headset",
    137     [SND_DEVICE_OUT_USB_HEADPHONES] = "usb-headphones",
    138     [SND_DEVICE_OUT_VOICE_USB_HEADSET] = "usb-headset",
    139     [SND_DEVICE_OUT_VOICE_USB_HEADPHONES] = "usb-headphones",
    140 
    141 
    142     /* Capture sound devices */
    143     [SND_DEVICE_IN_HANDSET_MIC] = "handset-mic",
    144     [SND_DEVICE_IN_SPEAKER_MIC] = "speaker-mic",
    145     [SND_DEVICE_IN_HEADSET_MIC] = "headset-mic",
    146     [SND_DEVICE_IN_HANDSET_MIC_AEC] = "handset-mic",
    147     [SND_DEVICE_IN_SPEAKER_MIC_AEC] = "voice-speaker-mic",
    148     [SND_DEVICE_IN_HEADSET_MIC_AEC] = "headset-mic",
    149     [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "voice-speaker-mic",
    150     [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "voice-headset-mic",
    151     [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic",
    152     [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic",
    153     [SND_DEVICE_IN_BT_SCO_MIC_WB] = "bt-sco-mic-wb",
    154     [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic",
    155     [SND_DEVICE_IN_VOICE_DMIC_EF] = "voice-dmic-ef",
    156     [SND_DEVICE_IN_VOICE_DMIC_BS] = "voice-dmic-bs",
    157     [SND_DEVICE_IN_VOICE_DMIC_EF_TMUS] = "voice-dmic-ef-tmus",
    158     [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF] = "voice-speaker-dmic-ef",
    159     [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS] = "voice-speaker-dmic-bs",
    160     [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = "voice-tty-full-headset-mic",
    161     [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = "voice-tty-vco-handset-mic",
    162     [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = "voice-tty-hco-headset-mic",
    163     [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic",
    164     [SND_DEVICE_IN_VOICE_REC_DMIC_EF] = "voice-rec-dmic-ef",
    165     [SND_DEVICE_IN_VOICE_REC_DMIC_BS] = "voice-rec-dmic-bs",
    166     [SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE] = "voice-rec-dmic-ef-fluence",
    167     [SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE] = "voice-rec-dmic-bs-fluence",
    168 };
    169 
    170 /* ACDB IDs (audio DSP path configuration IDs) for each sound device */
    171 static const int acdb_device_table[SND_DEVICE_MAX] = {
    172     [SND_DEVICE_NONE] = -1,
    173     [SND_DEVICE_OUT_HANDSET] = 7,
    174     [SND_DEVICE_OUT_SPEAKER] = 14,
    175     [SND_DEVICE_OUT_SPEAKER_REVERSE] = 14,
    176     [SND_DEVICE_OUT_SPEAKER_SAFE] = 14,
    177     [SND_DEVICE_OUT_HEADPHONES] = 10,
    178     [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = 10,
    179     [SND_DEVICE_OUT_VOICE_SPEAKER] = 14,
    180     [SND_DEVICE_OUT_VOICE_HEADPHONES] = 10,
    181     [SND_DEVICE_OUT_HDMI] = 18,
    182     [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 14,
    183     [SND_DEVICE_OUT_BT_SCO] = 22,
    184     [SND_DEVICE_OUT_BT_SCO_WB] = 39,
    185     [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = 81,
    186     [SND_DEVICE_OUT_VOICE_HANDSET] = 81,
    187     [SND_DEVICE_OUT_VOICE_HAC_HANDSET] = 81,
    188     [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = 17,
    189     [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = 17,
    190     [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = 37,
    191     [SND_DEVICE_OUT_USB_HEADSET] = 45,
    192     [SND_DEVICE_OUT_USB_HEADPHONES] = 45,
    193     [SND_DEVICE_OUT_VOICE_USB_HEADSET] = 45,
    194     [SND_DEVICE_OUT_VOICE_USB_HEADPHONES] = 45,
    195 
    196     [SND_DEVICE_IN_HANDSET_MIC] = 4,
    197     [SND_DEVICE_IN_SPEAKER_MIC] = 4,
    198     [SND_DEVICE_IN_HEADSET_MIC] = 8,
    199     [SND_DEVICE_IN_HANDSET_MIC_AEC] = 40,
    200     [SND_DEVICE_IN_SPEAKER_MIC_AEC] = 42,
    201     [SND_DEVICE_IN_HEADSET_MIC_AEC] = 47,
    202     [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = 11,
    203     [SND_DEVICE_IN_VOICE_HEADSET_MIC] = 8,
    204     [SND_DEVICE_IN_HDMI_MIC] = 4,
    205     [SND_DEVICE_IN_BT_SCO_MIC] = 21,
    206     [SND_DEVICE_IN_BT_SCO_MIC_WB] = 38,
    207     [SND_DEVICE_IN_CAMCORDER_MIC] = 61,
    208     [SND_DEVICE_IN_VOICE_DMIC_EF] = 6,
    209     [SND_DEVICE_IN_VOICE_DMIC_BS] = 5,
    210     [SND_DEVICE_IN_VOICE_DMIC_EF_TMUS] = 91,
    211     [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF] = 13,
    212     [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS] = 12,
    213     [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = 16,
    214     [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = 36,
    215     [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = 16,
    216     [SND_DEVICE_IN_VOICE_REC_MIC] = 62,
    217     /* TODO: Update with proper acdb ids */
    218     [SND_DEVICE_IN_VOICE_REC_DMIC_EF] = 62,
    219     [SND_DEVICE_IN_VOICE_REC_DMIC_BS] = 62,
    220     [SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE] = 6,
    221     [SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE] = 5,
    222 };
    223 
    224 #define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL)
    225 #define LOW_LATENCY_PLATFORM_DELAY (13*1000LL)
    226 
    227 static pthread_once_t check_op_once_ctl = PTHREAD_ONCE_INIT;
    228 static bool is_tmus = false;
    229 
    230 static void check_operator()
    231 {
    232     char value[PROPERTY_VALUE_MAX];
    233     int mccmnc;
    234     property_get("gsm.sim.operator.numeric",value,"0");
    235     mccmnc = atoi(value);
    236     ALOGD("%s: tmus mccmnc %d", __func__, mccmnc);
    237     switch(mccmnc) {
    238     /* TMUS MCC(310), MNC(490, 260, 026) */
    239     case 310490:
    240     case 310260:
    241     case 310026:
    242         is_tmus = true;
    243         break;
    244     }
    245 }
    246 
    247 bool is_operator_tmus()
    248 {
    249     pthread_once(&check_op_once_ctl, check_operator);
    250     return is_tmus;
    251 }
    252 
    253 static int set_echo_reference(struct mixer *mixer, const char* ec_ref)
    254 {
    255     struct mixer_ctl *ctl;
    256     const char *mixer_ctl_name = "EC_REF_RX";
    257 
    258     ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
    259     if (!ctl) {
    260         ALOGE("%s: Could not get ctl for mixer cmd - %s",
    261               __func__, mixer_ctl_name);
    262         return -EINVAL;
    263     }
    264     ALOGV("Setting EC Reference: %s", ec_ref);
    265     mixer_ctl_set_enum_by_string(ctl, ec_ref);
    266     return 0;
    267 }
    268 
    269 void *platform_init(struct audio_device *adev)
    270 {
    271     char platform[PROPERTY_VALUE_MAX];
    272     char baseband[PROPERTY_VALUE_MAX];
    273     char value[PROPERTY_VALUE_MAX];
    274     struct platform_data *my_data;
    275 
    276     adev->mixer = mixer_open(MIXER_CARD);
    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     /* If platform is Fusion3, load CSD Client specific symbols
    346      * Voice call is handled by MDM and apps processor talks to
    347      * MDM through CSD Client
    348      */
    349     property_get("ro.board.platform", platform, "");
    350     property_get("ro.baseband", baseband, "");
    351     if (!strcmp("msm8960", platform) && !strcmp("mdm", baseband)) {
    352         my_data->csd_client = dlopen(LIB_CSD_CLIENT, RTLD_NOW);
    353         if (my_data->csd_client == NULL)
    354             ALOGE("%s: DLOPEN failed for %s", __func__, LIB_CSD_CLIENT);
    355     }
    356 
    357     if (my_data->csd_client) {
    358         ALOGV("%s: DLOPEN successful for %s", __func__, LIB_CSD_CLIENT);
    359         my_data->csd_client_deinit = (csd_client_deinit_t)dlsym(my_data->csd_client,
    360                                                     "csd_client_deinit");
    361         my_data->csd_disable_device = (csd_disable_device_t)dlsym(my_data->csd_client,
    362                                                     "csd_client_disable_device");
    363         my_data->csd_enable_device = (csd_enable_device_t)dlsym(my_data->csd_client,
    364                                                     "csd_client_enable_device");
    365         my_data->csd_start_voice = (csd_start_voice_t)dlsym(my_data->csd_client,
    366                                                     "csd_client_start_voice");
    367         my_data->csd_stop_voice = (csd_stop_voice_t)dlsym(my_data->csd_client,
    368                                                     "csd_client_stop_voice");
    369         my_data->csd_volume = (csd_volume_t)dlsym(my_data->csd_client,
    370                                                     "csd_client_volume");
    371         my_data->csd_mic_mute = (csd_mic_mute_t)dlsym(my_data->csd_client,
    372                                                     "csd_client_mic_mute");
    373         my_data->csd_client_init = (csd_client_init_t)dlsym(my_data->csd_client,
    374                                                     "csd_client_init");
    375 
    376         if (my_data->csd_client_init == NULL) {
    377             ALOGE("%s: dlsym error %s for csd_client_init", __func__, dlerror());
    378         } else {
    379             my_data->csd_client_init();
    380         }
    381     }
    382 
    383     return my_data;
    384 }
    385 
    386 void platform_deinit(void *platform)
    387 {
    388     free(platform);
    389 }
    390 
    391 const char *platform_get_snd_device_name(snd_device_t snd_device)
    392 {
    393     if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX)
    394         return device_table[snd_device];
    395     else
    396         return "none";
    397 }
    398 
    399 void platform_add_backend_name(void *platform __unused, char *mixer_path,
    400                                snd_device_t snd_device)
    401 {
    402     if (snd_device == SND_DEVICE_IN_BT_SCO_MIC)
    403         strcat(mixer_path, " bt-sco");
    404     else if(snd_device == SND_DEVICE_OUT_BT_SCO)
    405         strcat(mixer_path, " bt-sco");
    406     else if (snd_device == SND_DEVICE_OUT_HDMI)
    407         strcat(mixer_path, " hdmi");
    408     else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HDMI)
    409         strcat(mixer_path, " speaker-and-hdmi");
    410     else if (snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
    411              snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB)
    412         strcat(mixer_path, " bt-sco-wb");
    413 }
    414 
    415 int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type)
    416 {
    417     int device_id;
    418     if (device_type == PCM_PLAYBACK)
    419         device_id = pcm_device_table[usecase][0];
    420     else
    421         device_id = pcm_device_table[usecase][1];
    422     return device_id;
    423 }
    424 
    425 int platform_get_snd_device_index(char *snd_device_index_name __unused)
    426 {
    427     return -ENODEV;
    428 }
    429 
    430 int platform_set_snd_device_acdb_id(snd_device_t snd_device __unused,
    431                                     unsigned int acdb_id __unused)
    432 {
    433     return -ENODEV;
    434 }
    435 
    436 int platform_get_default_app_type_v2(void *platform __unused, usecase_type_t type __unused,
    437                                      int *app_type __unused)
    438 {
    439     ALOGE("%s: Not implemented", __func__);
    440     return -ENOSYS;
    441 }
    442 
    443 int platform_get_snd_device_acdb_id(snd_device_t snd_device __unused)
    444 {
    445     ALOGE("%s: Not implemented", __func__);
    446     return -ENOSYS;
    447 }
    448 
    449 void platform_add_operator_specific_device(snd_device_t snd_device __unused,
    450                                            const char *operator __unused,
    451                                            const char *mixer_path __unused,
    452                                            unsigned int acdb_id __unused)
    453 {
    454 }
    455 
    456 int platform_send_audio_calibration(void *platform, snd_device_t snd_device)
    457 {
    458     struct platform_data *my_data = (struct platform_data *)platform;
    459     int acdb_dev_id, acdb_dev_type;
    460 
    461     acdb_dev_id = acdb_device_table[snd_device];
    462     if (acdb_dev_id < 0) {
    463         ALOGE("%s: Could not find acdb id for device(%d)",
    464               __func__, snd_device);
    465         return -EINVAL;
    466     }
    467     if (my_data->acdb_send_audio_cal) {
    468         ("%s: sending audio calibration for snd_device(%d) acdb_id(%d)",
    469               __func__, snd_device, acdb_dev_id);
    470         if (snd_device >= SND_DEVICE_OUT_BEGIN &&
    471                 snd_device < SND_DEVICE_OUT_END)
    472             acdb_dev_type = ACDB_DEV_TYPE_OUT;
    473         else
    474             acdb_dev_type = ACDB_DEV_TYPE_IN;
    475         my_data->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type);
    476     }
    477     return 0;
    478 }
    479 
    480 int platform_switch_voice_call_device_pre(void *platform)
    481 {
    482     struct platform_data *my_data = (struct platform_data *)platform;
    483     int ret = 0;
    484 
    485     if (my_data->csd_client != NULL &&
    486         voice_is_in_call(my_data->adev)) {
    487         /* This must be called before disabling the mixer controls on APQ side */
    488         if (my_data->csd_disable_device == NULL) {
    489             ALOGE("%s: dlsym error for csd_disable_device", __func__);
    490         } else {
    491             ret = my_data->csd_disable_device();
    492             if (ret < 0) {
    493                 ALOGE("%s: csd_client_disable_device, failed, error %d",
    494                       __func__, ret);
    495             }
    496         }
    497     }
    498     return ret;
    499 }
    500 
    501 int platform_switch_voice_call_device_post(void *platform,
    502                                            snd_device_t out_snd_device,
    503                                            snd_device_t in_snd_device)
    504 {
    505     struct platform_data *my_data = (struct platform_data *)platform;
    506     int acdb_rx_id, acdb_tx_id;
    507     int ret = 0;
    508 
    509     if (my_data->csd_client) {
    510         if (my_data->csd_enable_device == NULL) {
    511             ALOGE("%s: dlsym error for csd_enable_device",
    512                   __func__);
    513         } else {
    514             acdb_rx_id = acdb_device_table[out_snd_device];
    515             acdb_tx_id = acdb_device_table[in_snd_device];
    516 
    517             if (acdb_rx_id > 0 || acdb_tx_id > 0) {
    518                 ret = my_data->csd_enable_device(acdb_rx_id, acdb_tx_id,
    519                                                     my_data->adev->acdb_settings);
    520                 if (ret < 0) {
    521                     ALOGE("%s: csd_enable_device, failed, error %d",
    522                           __func__, ret);
    523                 }
    524             } else {
    525                 ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__,
    526                       acdb_rx_id, acdb_tx_id);
    527             }
    528         }
    529     }
    530 
    531     return ret;
    532 }
    533 
    534 int platform_start_voice_call(void *platform, uint32_t vsid __unused)
    535 {
    536     struct platform_data *my_data = (struct platform_data *)platform;
    537     int ret = 0;
    538 
    539     if (my_data->csd_client) {
    540         if (my_data->csd_start_voice == NULL) {
    541             ALOGE("dlsym error for csd_client_start_voice");
    542             ret = -ENOSYS;
    543         } else {
    544             ret = my_data->csd_start_voice();
    545             if (ret < 0) {
    546                 ALOGE("%s: csd_start_voice error %d\n", __func__, ret);
    547             }
    548         }
    549     }
    550 
    551     return ret;
    552 }
    553 
    554 int platform_stop_voice_call(void *platform, uint32_t vsid __unused)
    555 {
    556     struct platform_data *my_data = (struct platform_data *)platform;
    557     int ret = 0;
    558 
    559     if (my_data->csd_client) {
    560         if (my_data->csd_stop_voice == NULL) {
    561             ALOGE("dlsym error for csd_stop_voice");
    562         } else {
    563             ret = my_data->csd_stop_voice();
    564             if (ret < 0) {
    565                 ALOGE("%s: csd_stop_voice error %d\n", __func__, ret);
    566             }
    567         }
    568     }
    569 
    570     return ret;
    571 }
    572 
    573 void platform_set_speaker_gain_in_combo(struct audio_device *adev __unused,
    574                                         snd_device_t snd_device  __unused,
    575                                         bool enable __unused) {
    576 }
    577 
    578 int platform_set_voice_volume(void *platform, int volume)
    579 {
    580     struct platform_data *my_data = (struct platform_data *)platform;
    581     int ret = 0;
    582 
    583     if (my_data->csd_client) {
    584         if (my_data->csd_volume == NULL) {
    585             ALOGE("%s: dlsym error for csd_volume", __func__);
    586         } else {
    587             ret = my_data->csd_volume(volume);
    588             if (ret < 0) {
    589                 ALOGE("%s: csd_volume error %d", __func__, ret);
    590             }
    591         }
    592     } else {
    593         ALOGE("%s: No CSD Client present", __func__);
    594     }
    595 
    596     return ret;
    597 }
    598 
    599 int platform_set_mic_mute(void *platform, bool state)
    600 {
    601     struct platform_data *my_data = (struct platform_data *)platform;
    602     int ret = 0;
    603 
    604     if (my_data->adev->mode == AUDIO_MODE_IN_CALL) {
    605         if (my_data->csd_client) {
    606             if (my_data->csd_mic_mute == NULL) {
    607                 ALOGE("%s: dlsym error for csd_mic_mute", __func__);
    608             } else {
    609                 ret = my_data->csd_mic_mute(state);
    610                 if (ret < 0) {
    611                     ALOGE("%s: csd_mic_mute error %d", __func__, ret);
    612                 }
    613             }
    614         } else {
    615             ALOGE("%s: No CSD Client present", __func__);
    616         }
    617     }
    618 
    619     return ret;
    620 }
    621 
    622 int platform_set_device_mute(void *platform __unused, bool state __unused, char *dir __unused)
    623 {
    624     ALOGE("%s: Not implemented", __func__);
    625     return -ENOSYS;
    626 }
    627 
    628 snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices)
    629 {
    630     struct platform_data *my_data = (struct platform_data *)platform;
    631     struct audio_device *adev = my_data->adev;
    632     audio_mode_t mode = adev->mode;
    633     snd_device_t snd_device = SND_DEVICE_NONE;
    634 
    635     ALOGV("%s: enter: output devices(%#x)", __func__, devices);
    636     if (devices == AUDIO_DEVICE_NONE ||
    637         devices & AUDIO_DEVICE_BIT_IN) {
    638         ALOGV("%s: Invalid output devices (%#x)", __func__, devices);
    639         goto exit;
    640     }
    641 
    642     if (voice_is_in_call(adev)) {
    643         if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
    644             devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
    645             if (adev->voice.tty_mode == TTY_MODE_FULL)
    646                 snd_device = SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES;
    647             else if (adev->voice.tty_mode == TTY_MODE_VCO)
    648                 snd_device = SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES;
    649             else if (adev->voice.tty_mode == TTY_MODE_HCO)
    650                 snd_device = SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET;
    651             else
    652                 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES;
    653         } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
    654             if (adev->bt_wb_speech_enabled) {
    655                 snd_device = SND_DEVICE_OUT_BT_SCO_WB;
    656             } else {
    657                 snd_device = SND_DEVICE_OUT_BT_SCO;
    658             }
    659         } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
    660             snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
    661         } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
    662             if (is_operator_tmus())
    663                 snd_device = SND_DEVICE_OUT_VOICE_HANDSET_TMUS;
    664             else
    665                 snd_device = SND_DEVICE_OUT_HANDSET;
    666         }
    667         if (snd_device != SND_DEVICE_NONE) {
    668             goto exit;
    669         }
    670     }
    671 
    672     if (popcount(devices) == 2) {
    673         if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
    674                         AUDIO_DEVICE_OUT_SPEAKER)) {
    675             snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
    676         } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
    677                                AUDIO_DEVICE_OUT_SPEAKER)) {
    678             snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
    679         } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL |
    680                                AUDIO_DEVICE_OUT_SPEAKER)) {
    681             snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
    682         } else {
    683             ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
    684             goto exit;
    685         }
    686         if (snd_device != SND_DEVICE_NONE) {
    687             goto exit;
    688         }
    689     }
    690 
    691     if (popcount(devices) != 1) {
    692         ALOGE("%s: Invalid output devices(%#x)", __func__, devices);
    693         goto exit;
    694     }
    695 
    696     if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
    697         devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
    698         snd_device = SND_DEVICE_OUT_HEADPHONES;
    699     } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
    700         /*
    701          * Perform device switch only if acdb tuning is different between SPEAKER & SPEAKER_REVERSE,
    702          * Or there will be a small pause while performing device switch.
    703          */
    704         if (my_data->speaker_lr_swap &&
    705             (acdb_device_table[SND_DEVICE_OUT_SPEAKER] !=
    706             acdb_device_table[SND_DEVICE_OUT_SPEAKER_REVERSE]))
    707             snd_device = SND_DEVICE_OUT_SPEAKER_REVERSE;
    708         else
    709             snd_device = SND_DEVICE_OUT_SPEAKER;
    710     } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
    711         if (adev->bt_wb_speech_enabled) {
    712             snd_device = SND_DEVICE_OUT_BT_SCO_WB;
    713         } else {
    714             snd_device = SND_DEVICE_OUT_BT_SCO;
    715         }
    716     } else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
    717         snd_device = SND_DEVICE_OUT_HDMI ;
    718     } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
    719         snd_device = SND_DEVICE_OUT_HANDSET;
    720     } else {
    721         ALOGE("%s: Unknown device(s) %#x", __func__, devices);
    722     }
    723 exit:
    724     ALOGV("%s: exit: snd_device(%s)", __func__, device_table[snd_device]);
    725     return snd_device;
    726 }
    727 
    728 snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device)
    729 {
    730     struct platform_data *my_data = (struct platform_data *)platform;
    731     struct audio_device *adev = my_data->adev;
    732     audio_source_t  source = (adev->active_input == NULL) ?
    733                                 AUDIO_SOURCE_DEFAULT : adev->active_input->source;
    734 
    735     audio_mode_t    mode   = adev->mode;
    736     audio_devices_t in_device = ((adev->active_input == NULL) ?
    737                                     AUDIO_DEVICE_NONE : adev->active_input->device)
    738                                 & ~AUDIO_DEVICE_BIT_IN;
    739     audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
    740                                 AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
    741     snd_device_t snd_device = SND_DEVICE_NONE;
    742 
    743     ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
    744           __func__, out_device, in_device);
    745     if ((out_device != AUDIO_DEVICE_NONE) && voice_is_in_call(adev)) {
    746         if (adev->voice.tty_mode != TTY_MODE_OFF) {
    747             if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
    748                 out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
    749                 switch (adev->voice.tty_mode) {
    750                 case TTY_MODE_FULL:
    751                     snd_device = SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC;
    752                     break;
    753                 case TTY_MODE_VCO:
    754                     snd_device = SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC;
    755                     break;
    756                 case TTY_MODE_HCO:
    757                     snd_device = SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC;
    758                     break;
    759                 default:
    760                     ALOGE("%s: Invalid TTY mode (%#x)", __func__, adev->voice.tty_mode);
    761                 }
    762                 goto exit;
    763             }
    764         }
    765         if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
    766             out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
    767             if (my_data->fluence_in_voice_call == false) {
    768                 snd_device = SND_DEVICE_IN_HANDSET_MIC;
    769             } else {
    770                 if (my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
    771                     if (is_operator_tmus())
    772                         snd_device = SND_DEVICE_IN_VOICE_DMIC_EF_TMUS;
    773                     else
    774                         snd_device = SND_DEVICE_IN_VOICE_DMIC_EF;
    775                 } else if(my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE)
    776                     snd_device = SND_DEVICE_IN_VOICE_DMIC_BS;
    777                 else
    778                     snd_device = SND_DEVICE_IN_HANDSET_MIC;
    779             }
    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) {
    783             if (adev->bt_wb_speech_enabled) {
    784                 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
    785             } else {
    786                 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
    787             }
    788         } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
    789             if (my_data->fluence_in_voice_call && my_data->fluence_in_spkr_mode &&
    790                     my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
    791                 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF;
    792             } else if (my_data->fluence_in_voice_call && my_data->fluence_in_spkr_mode &&
    793                     my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE) {
    794                 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS;
    795             } else {
    796                 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
    797             }
    798         }
    799     } else if (source == AUDIO_SOURCE_CAMCORDER) {
    800         if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
    801             in_device & AUDIO_DEVICE_IN_BACK_MIC) {
    802             snd_device = SND_DEVICE_IN_CAMCORDER_MIC;
    803         }
    804     } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) {
    805         if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
    806             if (my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
    807                 if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
    808                     snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_EF;
    809                 else if (my_data->fluence_in_voice_rec)
    810                     snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE;
    811             } else if (my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE) {
    812                 if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
    813                     snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_BS;
    814                 else if (my_data->fluence_in_voice_rec)
    815                     snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE;
    816             }
    817 
    818             if (snd_device == SND_DEVICE_NONE) {
    819                 snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
    820             }
    821         }
    822     } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
    823             mode == AUDIO_MODE_IN_COMMUNICATION) {
    824         if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
    825             in_device = AUDIO_DEVICE_IN_BACK_MIC;
    826         if (adev->active_input) {
    827             if (adev->active_input->enable_aec) {
    828                 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
    829                     snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
    830                 } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
    831                     snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
    832                 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
    833                     snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
    834                 }
    835                 set_echo_reference(adev->mixer, "SLIM_RX");
    836             } else
    837                 set_echo_reference(adev->mixer, "NONE");
    838         }
    839     } 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) {
    852             snd_device = SND_DEVICE_IN_HANDSET_MIC;
    853         } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
    854             snd_device = SND_DEVICE_IN_SPEAKER_MIC;
    855         } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
    856             snd_device = SND_DEVICE_IN_HEADSET_MIC;
    857         } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
    858             if (adev->bt_wb_speech_enabled) {
    859                 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
    860             } else {
    861                 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
    862             }
    863         } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) {
    864             snd_device = SND_DEVICE_IN_HDMI_MIC;
    865         } else {
    866             ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
    867             ALOGW("%s: Using default handset-mic", __func__);
    868             snd_device = SND_DEVICE_IN_HANDSET_MIC;
    869         }
    870     } else {
    871         if (out_device & AUDIO_DEVICE_OUT_EARPIECE) {
    872             snd_device = SND_DEVICE_IN_HANDSET_MIC;
    873         } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
    874             snd_device = SND_DEVICE_IN_HEADSET_MIC;
    875         } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
    876             snd_device = SND_DEVICE_IN_SPEAKER_MIC;
    877         } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
    878             snd_device = SND_DEVICE_IN_HANDSET_MIC;
    879         } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
    880             if (adev->bt_wb_speech_enabled) {
    881                 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
    882             } else {
    883                 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
    884             }
    885         } else if (out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
    886             snd_device = SND_DEVICE_IN_HDMI_MIC;
    887         } else {
    888             ALOGE("%s: Unknown output device(s) %#x", __func__, out_device);
    889             ALOGW("%s: Using default handset-mic", __func__);
    890             snd_device = SND_DEVICE_IN_HANDSET_MIC;
    891         }
    892     }
    893 exit:
    894     ALOGV("%s: exit: in_snd_device(%s)", __func__, device_table[snd_device]);
    895     return snd_device;
    896 }
    897 
    898 int platform_set_hdmi_channels(void *platform,  int channel_count)
    899 {
    900     struct platform_data *my_data = (struct platform_data *)platform;
    901     struct audio_device *adev = my_data->adev;
    902     struct mixer_ctl *ctl;
    903     const char *channel_cnt_str = NULL;
    904     const char *mixer_ctl_name = "HDMI_RX Channels";
    905     switch (channel_count) {
    906     case 8:
    907         channel_cnt_str = "Eight"; break;
    908     case 7:
    909         channel_cnt_str = "Seven"; break;
    910     case 6:
    911         channel_cnt_str = "Six"; break;
    912     case 5:
    913         channel_cnt_str = "Five"; break;
    914     case 4:
    915         channel_cnt_str = "Four"; break;
    916     case 3:
    917         channel_cnt_str = "Three"; break;
    918     default:
    919         channel_cnt_str = "Two"; break;
    920     }
    921     ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
    922     if (!ctl) {
    923         ALOGE("%s: Could not get ctl for mixer cmd - %s",
    924               __func__, mixer_ctl_name);
    925         return -EINVAL;
    926     }
    927     ALOGV("HDMI channel count: %s", channel_cnt_str);
    928     mixer_ctl_set_enum_by_string(ctl, channel_cnt_str);
    929     return 0;
    930 }
    931 
    932 int platform_edid_get_max_channels(void *platform __unused)
    933 {
    934     FILE *file;
    935     struct audio_block_header header;
    936     char block[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE];
    937     char *sad = block;
    938     int num_audio_blocks;
    939     int channel_count;
    940     int max_channels = 0;
    941     int i;
    942 
    943     file = fopen(AUDIO_DATA_BLOCK_PATH, "rb");
    944     if (file == NULL) {
    945         ALOGE("Unable to open '%s'", AUDIO_DATA_BLOCK_PATH);
    946         return 0;
    947     }
    948 
    949     /* Read audio block header */
    950     fread(&header, 1, sizeof(header), file);
    951 
    952     /* Read SAD blocks, clamping the maximum size for safety */
    953     if (header.length > (int)sizeof(block))
    954         header.length = (int)sizeof(block);
    955     fread(&block, header.length, 1, file);
    956 
    957     fclose(file);
    958 
    959     /* Calculate the number of SAD blocks */
    960     num_audio_blocks = header.length / SAD_BLOCK_SIZE;
    961 
    962     for (i = 0; i < num_audio_blocks; i++) {
    963         /* Only consider LPCM blocks */
    964         if ((sad[0] >> 3) != EDID_FORMAT_LPCM)
    965             continue;
    966 
    967         channel_count = (sad[0] & 0x7) + 1;
    968         if (channel_count > max_channels)
    969             max_channels = channel_count;
    970 
    971         /* Advance to next block */
    972         sad += 3;
    973     }
    974 
    975     return max_channels;
    976 }
    977 
    978 int platform_set_incall_recording_session_id(void *platform __unused,
    979                                              uint32_t session_id __unused, int rec_mode __unused)
    980 {
    981     ALOGE("%s: Not implemented", __func__);
    982     return -ENOSYS;
    983 }
    984 
    985 int platform_stop_incall_recording_usecase(void *platform __unused)
    986 {
    987     ALOGE("%s: Not implemented", __func__);
    988     return -ENOSYS;
    989 }
    990 
    991 int platform_start_incall_music_usecase(void *platform __unused)
    992 {
    993     ALOGE("%s: Not implemented", __func__);
    994     return -ENOSYS;
    995 }
    996 
    997 int platform_stop_incall_music_usecase(void *platform __unused)
    998 {
    999     ALOGE("%s: Not implemented", __func__);
   1000     return -ENOSYS;
   1001 }
   1002 
   1003 int platform_set_parameters(void *platform __unused,
   1004                             struct str_parms *parms __unused)
   1005 {
   1006     ALOGE("%s: Not implemented", __func__);
   1007     return -ENOSYS;
   1008 }
   1009 
   1010 /* Delay in Us */
   1011 int64_t platform_render_latency(audio_usecase_t usecase)
   1012 {
   1013     switch (usecase) {
   1014         case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER:
   1015             return DEEP_BUFFER_PLATFORM_DELAY;
   1016         case USECASE_AUDIO_PLAYBACK_LOW_LATENCY:
   1017             return LOW_LATENCY_PLATFORM_DELAY;
   1018         default:
   1019             return 0;
   1020     }
   1021 }
   1022 
   1023 int platform_switch_voice_call_enable_device_config(void *platform __unused,
   1024                                                     snd_device_t out_snd_device __unused,
   1025                                                     snd_device_t in_snd_device __unused)
   1026 {
   1027     return 0;
   1028 }
   1029 
   1030 int platform_switch_voice_call_usecase_route_post(void *platform __unused,
   1031                                                   snd_device_t out_snd_device __unused,
   1032                                                   snd_device_t in_snd_device __unused)
   1033 {
   1034     return 0;
   1035 }
   1036 
   1037 int platform_get_sample_rate(void *platform __unused, uint32_t *rate __unused)
   1038 {
   1039     return -ENOSYS;
   1040 }
   1041 
   1042 int platform_get_usecase_index(const char * usecase __unused)
   1043 {
   1044     return -ENOSYS;
   1045 }
   1046 
   1047 int platform_set_usecase_pcm_id(audio_usecase_t usecase __unused, int32_t type __unused,
   1048                                 int32_t pcm_id __unused)
   1049 {
   1050     return -ENOSYS;
   1051 }
   1052 
   1053 int platform_set_snd_device_backend(snd_device_t device __unused,
   1054                                     const char *backend __unused,
   1055                                     const char *hw_interface __unused)
   1056 {
   1057     return -ENOSYS;
   1058 }
   1059 
   1060 void platform_set_echo_reference(struct audio_device *adev __unused,
   1061                                  bool enable __unused,
   1062                                  audio_devices_t out_device __unused)
   1063 {
   1064     return;
   1065 }
   1066 
   1067 #define DEFAULT_NOMINAL_SPEAKER_GAIN 20
   1068 int ramp_speaker_gain(struct audio_device *adev, bool ramp_up, int target_ramp_up_gain) {
   1069     // backup_gain: gain to try to set in case of an error during ramp
   1070     int start_gain, end_gain, step, backup_gain, i;
   1071     bool error = false;
   1072     const struct mixer_ctl *ctl;
   1073     const char *mixer_ctl_name_gain_left = "Left Speaker Gain";
   1074     const char *mixer_ctl_name_gain_right = "Right Speaker Gain";
   1075     struct mixer_ctl *ctl_left = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name_gain_left);
   1076     struct mixer_ctl *ctl_right = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name_gain_right);
   1077     if (!ctl_left || !ctl_right) {
   1078         ALOGE("%s: Could not get ctl for mixer cmd - %s or %s, not applying speaker gain ramp",
   1079                       __func__, mixer_ctl_name_gain_left, mixer_ctl_name_gain_right);
   1080         return -EINVAL;
   1081     } else if ((mixer_ctl_get_num_values(ctl_left) != 1)
   1082             || (mixer_ctl_get_num_values(ctl_right) != 1)) {
   1083         ALOGE("%s: Unexpected num values for mixer cmd - %s or %s, not applying speaker gain ramp",
   1084                               __func__, mixer_ctl_name_gain_left, mixer_ctl_name_gain_right);
   1085         return -EINVAL;
   1086     }
   1087     if (ramp_up) {
   1088         start_gain = 0;
   1089         end_gain = target_ramp_up_gain > 0 ? target_ramp_up_gain : DEFAULT_NOMINAL_SPEAKER_GAIN;
   1090         step = +1;
   1091         backup_gain = end_gain;
   1092     } else {
   1093         // using same gain on left and right
   1094         const int left_gain = mixer_ctl_get_value(ctl_left, 0);
   1095         start_gain = left_gain > 0 ? left_gain : DEFAULT_NOMINAL_SPEAKER_GAIN;
   1096         end_gain = 0;
   1097         step = -1;
   1098         backup_gain = start_gain;
   1099     }
   1100     for (i = start_gain ; i != (end_gain + step) ; i += step) {
   1101         //ALOGV("setting speaker gain to %d", i);
   1102         if (mixer_ctl_set_value(ctl_left, 0, i)) {
   1103             ALOGE("%s: error setting %s to %d during gain ramp",
   1104                     __func__, mixer_ctl_name_gain_left, i);
   1105             error = true;
   1106             break;
   1107         }
   1108         if (mixer_ctl_set_value(ctl_right, 0, i)) {
   1109             ALOGE("%s: error setting %s to %d during gain ramp",
   1110                     __func__, mixer_ctl_name_gain_right, i);
   1111             error = true;
   1112             break;
   1113         }
   1114         usleep(1000);
   1115     }
   1116     if (error) {
   1117         // an error occured during the ramp, let's still try to go back to a safe volume
   1118         if (mixer_ctl_set_value(ctl_left, 0, backup_gain)) {
   1119             ALOGE("%s: error restoring left gain to %d", __func__, backup_gain);
   1120         }
   1121         if (mixer_ctl_set_value(ctl_right, 0, backup_gain)) {
   1122             ALOGE("%s: error restoring right gain to %d", __func__, backup_gain);
   1123         }
   1124     }
   1125     return start_gain;
   1126 }
   1127 
   1128 int platform_set_swap_mixer(struct audio_device *adev, bool swap_channels)
   1129 {
   1130     const char *mixer_ctl_name = "Swap channel";
   1131     struct mixer_ctl *ctl;
   1132     const char *mixer_path;
   1133     struct platform_data *my_data = (struct platform_data *)adev->platform;
   1134 
   1135     // forced to set to swap, but device not rotated ... ignore set
   1136     if (swap_channels && !my_data->speaker_lr_swap)
   1137         return 0;
   1138 
   1139     ALOGV("%s:", __func__);
   1140 
   1141     if (swap_channels) {
   1142         mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER_REVERSE);
   1143         audio_route_apply_and_update_path(adev->audio_route, mixer_path);
   1144     } else {
   1145         mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER);
   1146         audio_route_apply_and_update_path(adev->audio_route, mixer_path);
   1147     }
   1148 
   1149     ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
   1150     if (!ctl) {
   1151         ALOGE("%s: Could not get ctl for mixer cmd - %s",__func__, mixer_ctl_name);
   1152         return -EINVAL;
   1153     }
   1154 
   1155     if (mixer_ctl_set_value(ctl, 0, swap_channels) < 0) {
   1156         ALOGE("%s: Could not set reverse cotrol %d",__func__, swap_channels);
   1157         return -EINVAL;
   1158     }
   1159 
   1160     ALOGV("platfor_force_swap_channel :: Channel orientation ( %s ) ",
   1161            swap_channels?"R --> L":"L --> R");
   1162 
   1163     return 0;
   1164 }
   1165 
   1166 int platform_check_and_set_swap_lr_channels(struct audio_device *adev, bool swap_channels)
   1167 {
   1168     // only update if there is active pcm playback on speaker
   1169     struct audio_usecase *usecase;
   1170     struct listnode *node;
   1171     struct platform_data *my_data = (struct platform_data *)adev->platform;
   1172 
   1173     my_data->speaker_lr_swap = swap_channels;
   1174 
   1175     return platform_set_swap_channels(adev, swap_channels);
   1176 }
   1177 
   1178 int platform_set_swap_channels(struct audio_device *adev, bool swap_channels)
   1179 {
   1180     // only update if there is active pcm playback on speaker
   1181     struct audio_usecase *usecase;
   1182     struct listnode *node;
   1183     struct platform_data *my_data = (struct platform_data *)adev->platform;
   1184 
   1185     // do not swap channels in audio modes with concurrent capture and playback
   1186     // as this may break the echo reference
   1187     if ((adev->mode == AUDIO_MODE_IN_COMMUNICATION) || (adev->mode == AUDIO_MODE_IN_CALL)) {
   1188         ALOGV("%s: will not swap due to audio mode %d", __func__, adev->mode);
   1189         return 0;
   1190     }
   1191 
   1192     list_for_each(node, &adev->usecase_list) {
   1193         usecase = node_to_item(node, struct audio_usecase, list);
   1194         if (usecase->type == PCM_PLAYBACK &&
   1195                 usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
   1196             /*
   1197              * If acdb tuning is different for SPEAKER_REVERSE, it is must
   1198              * to perform device switch to disable the current backend to
   1199              * enable it with new acdb data.
   1200              */
   1201             if (acdb_device_table[SND_DEVICE_OUT_SPEAKER] !=
   1202                 acdb_device_table[SND_DEVICE_OUT_SPEAKER_REVERSE]) {
   1203                 const int initial_skpr_gain = ramp_speaker_gain(adev, false /*ramp_up*/, -1);
   1204                 select_devices(adev, usecase->id);
   1205                 if (initial_skpr_gain != -EINVAL)
   1206                     ramp_speaker_gain(adev, true /*ramp_up*/, initial_skpr_gain);
   1207 
   1208             } else {
   1209                 platform_set_swap_mixer(adev, swap_channels);
   1210             }
   1211             break;
   1212         }
   1213     }
   1214 
   1215     return 0;
   1216 }
   1217 
   1218 bool platform_send_gain_dep_cal(void *platform __unused,
   1219                                 int level __unused)
   1220 {
   1221     return true;
   1222 }
   1223 
   1224 int platform_can_split_snd_device(snd_device_t in_snd_device __unused,
   1225                                    int *num_devices __unused,
   1226                                    snd_device_t *out_snd_devices __unused)
   1227 {
   1228     return -ENOSYS;
   1229 }
   1230 
   1231 bool platform_check_backends_match(snd_device_t snd_device1 __unused,
   1232                                    snd_device_t snd_device2 __unused)
   1233 {
   1234     return true;
   1235 }
   1236 
   1237 int platform_get_snd_device_name_extn(void *platform __unused,
   1238                                       snd_device_t snd_device,
   1239                                       char *device_name)
   1240 {
   1241     strlcpy(device_name, platform_get_snd_device_name(snd_device),
   1242             DEVICE_NAME_MAX_SIZE);
   1243     return 0;
   1244 }
   1245 
   1246 bool platform_check_and_set_playback_backend_cfg(struct audio_device* adev __unused,
   1247                                               struct audio_usecase *usecase __unused,
   1248                                               snd_device_t snd_device __unused)
   1249 {
   1250     return false;
   1251 }
   1252 
   1253 bool platform_check_and_set_capture_backend_cfg(struct audio_device* adev __unused,
   1254     struct audio_usecase *usecase __unused, snd_device_t snd_device __unused)
   1255 {
   1256     return false;
   1257 }
   1258 
   1259 bool platform_add_gain_level_mapping(struct amp_db_and_gain_table *tbl_entry __unused)
   1260 {
   1261     return false;
   1262 }
   1263 
   1264 int platform_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl __unused,
   1265                                     int table_size __unused)
   1266 {
   1267     return 0;
   1268 }
   1269 
   1270 int platform_snd_card_update(void *platform __unused,
   1271                              card_status_t status __unused)
   1272 {
   1273     return -1;
   1274 }
   1275 
   1276 int platform_get_snd_device_backend_index(snd_device_t snd_device __unused)
   1277 {
   1278     return -ENOSYS;
   1279 }
   1280 
   1281 void platform_check_and_update_copp_sample_rate(void* platform __unused, snd_device_t snd_device __unused,
   1282                                                 unsigned int stream_sr __unused, int* sample_rate __unused)
   1283 {
   1284 
   1285 }
   1286 
   1287 int platform_send_audio_calibration_v2(void *platform __unused, struct audio_usecase *usecase __unused,
   1288                                        int app_type __unused, int sample_rate __unused)
   1289 {
   1290     return -ENOSYS;
   1291 }
   1292 
   1293 bool platform_supports_app_type_cfg() { return false; }
   1294 
   1295 void platform_add_app_type(const char *uc_type __unused,
   1296                            const char *mode __unused,
   1297                            int bw __unused, int app_type __unused,
   1298                            int max_sr __unused) {}
   1299 
   1300 int platform_get_app_type_v2(void *platform __unused,
   1301                              enum usecase_type_t type __unused,
   1302                              const char *mode __unused,
   1303                              int bw __unused, int sr __unused,
   1304                              int *app_type __unused) {
   1305     return -ENOSYS;
   1306 }
   1307 
   1308 int platform_set_sidetone(struct audio_device *adev,
   1309                           snd_device_t out_snd_device,
   1310                           bool enable, char *str)
   1311 {
   1312     int ret;
   1313     if (out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
   1314         out_snd_device == SND_DEVICE_OUT_VOICE_USB_HEADSET) {
   1315             ret = audio_extn_usb_enable_sidetone(out_snd_device, enable);
   1316             if (ret)
   1317                 ALOGI("%s: usb device %d does not support device sidetone\n",
   1318                   __func__, out_snd_device);
   1319     } else {
   1320         ALOGV("%s: sidetone out device(%d) mixer cmd = %s\n",
   1321               __func__, out_snd_device, str);
   1322         if (enable)
   1323             audio_route_apply_and_update_path(adev->audio_route, str);
   1324         else
   1325             audio_route_reset_and_update_path(adev->audio_route, str);
   1326     }
   1327     return 0;
   1328 }
   1329 
   1330 int platform_get_mmap_data_fd(void *platform __unused, int fe_dev __unused, int dir __unused,
   1331                               int *fd __unused, uint32_t *size __unused)
   1332 {
   1333     return -ENOSYS;
   1334 }
   1335 
   1336 bool platform_sound_trigger_usecase_needs_event(audio_usecase_t uc_id __unused)
   1337 {
   1338     return false;
   1339 }
   1340 
   1341 bool platform_snd_device_has_speaker(snd_device_t dev __unused) {
   1342     return false;
   1343 }
   1344 
   1345 bool platform_set_microphone_characteristic(void *platform __unused,
   1346                                             struct audio_microphone_characteristic_t mic __unused) {
   1347     return -ENOSYS;
   1348 }
   1349 
   1350 int platform_get_microphones(void *platform __unused,
   1351                              struct audio_microphone_characteristic_t *mic_array __unused,
   1352                              size_t *mic_count __unused) {
   1353     return -ENOSYS;
   1354 }
   1355 
   1356 int platform_get_active_microphones(void *platform __unused, unsigned int channels __unused,
   1357                                     audio_usecase_t usecase __unused,
   1358                                     struct audio_microphone_characteristic_t *mic_array __unused,
   1359                                     size_t *mic_count __unused) {
   1360     return -ENOSYS;
   1361 }
   1362 
   1363 int platform_set_usb_service_interval(void *platform __unused,
   1364                                       bool playback __unused,
   1365                                       unsigned long service_interval __unused,
   1366                                       bool *reconfig)
   1367 {
   1368     *reconfig = false;
   1369     return 0;
   1370 }
   1371 
   1372 int platform_set_backend_cfg(const struct audio_device* adev __unused,
   1373                              snd_device_t snd_device __unused,
   1374                              const struct audio_backend_cfg *backend_cfg __unused)
   1375 {
   1376     return -1;
   1377 }
   1378 
   1379 int platform_set_acdb_metainfo_key(void *platform __unused,
   1380                                    char *name __unused,
   1381                                    int key __unused) {
   1382     return -ENOSYS;
   1383 }
   1384