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 <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 LIB_ACDB_LOADER "libacdbloader.so"
     30 #define LIB_CSD_CLIENT "libcsd-client.so"
     31 
     32 #define DUALMIC_CONFIG_NONE 0      /* Target does not contain 2 mics */
     33 #define DUALMIC_CONFIG_ENDFIRE 1
     34 #define DUALMIC_CONFIG_BROADSIDE 2
     35 
     36 /*
     37  * This is the sysfs path for the HDMI audio data block
     38  */
     39 #define AUDIO_DATA_BLOCK_PATH "/sys/class/graphics/fb1/audio_data_block"
     40 #define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
     41 
     42 /*
     43  * This file will have a maximum of 38 bytes:
     44  *
     45  * 4 bytes: number of audio blocks
     46  * 4 bytes: total length of Short Audio Descriptor (SAD) blocks
     47  * Maximum 10 * 3 bytes: SAD blocks
     48  */
     49 #define MAX_SAD_BLOCKS      10
     50 #define SAD_BLOCK_SIZE      3
     51 
     52 /* EDID format ID for LPCM audio */
     53 #define EDID_FORMAT_LPCM    1
     54 
     55 struct audio_block_header
     56 {
     57     int reserved;
     58     int length;
     59 };
     60 
     61 
     62 typedef void (*acdb_deallocate_t)();
     63 typedef int  (*acdb_init_t)();
     64 typedef void (*acdb_send_audio_cal_t)(int, int);
     65 typedef void (*acdb_send_voice_cal_t)(int, int);
     66 
     67 typedef int (*csd_client_init_t)();
     68 typedef int (*csd_client_deinit_t)();
     69 typedef int (*csd_disable_device_t)();
     70 typedef int (*csd_enable_device_t)(int, int, uint32_t);
     71 typedef int (*csd_volume_t)(int);
     72 typedef int (*csd_mic_mute_t)(int);
     73 typedef int (*csd_start_voice_t)();
     74 typedef int (*csd_stop_voice_t)();
     75 
     76 
     77 /* Audio calibration related functions */
     78 struct platform_data {
     79     struct audio_device *adev;
     80     bool fluence_in_spkr_mode;
     81     bool fluence_in_voice_call;
     82     bool fluence_in_voice_rec;
     83     int  dualmic_config;
     84     bool speaker_lr_swap;
     85 
     86     void *acdb_handle;
     87     acdb_init_t acdb_init;
     88     acdb_deallocate_t acdb_deallocate;
     89     acdb_send_audio_cal_t acdb_send_audio_cal;
     90     acdb_send_voice_cal_t acdb_send_voice_cal;
     91 
     92     /* CSD Client related functions for voice call */
     93     void *csd_client;
     94     csd_client_init_t csd_client_init;
     95     csd_client_deinit_t csd_client_deinit;
     96     csd_disable_device_t csd_disable_device;
     97     csd_enable_device_t csd_enable_device;
     98     csd_volume_t csd_volume;
     99     csd_mic_mute_t csd_mic_mute;
    100     csd_start_voice_t csd_start_voice;
    101     csd_stop_voice_t csd_stop_voice;
    102 };
    103 
    104 static const int pcm_device_table[AUDIO_USECASE_MAX][2] = {
    105     [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
    106     [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {14, 14},
    107     [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
    108     [USECASE_AUDIO_RECORD] = {0, 0},
    109     [USECASE_AUDIO_RECORD_LOW_LATENCY] = {14, 14},
    110     [USECASE_VOICE_CALL] = {12, 12},
    111 };
    112 
    113 /* Array to store sound devices */
    114 static const char * const device_table[SND_DEVICE_MAX] = {
    115     [SND_DEVICE_NONE] = "none",
    116     /* Playback sound devices */
    117     [SND_DEVICE_OUT_HANDSET] = "handset",
    118     [SND_DEVICE_OUT_SPEAKER] = "speaker",
    119     [SND_DEVICE_OUT_SPEAKER_REVERSE] = "speaker-reverse",
    120     [SND_DEVICE_OUT_HEADPHONES] = "headphones",
    121     [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones",
    122     [SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker",
    123     [SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones",
    124     [SND_DEVICE_OUT_HDMI] = "hdmi",
    125     [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
    126     [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
    127     [SND_DEVICE_OUT_BT_SCO_WB] = "bt-sco-headset-wb",
    128     [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = "voice-handset-tmus",
    129     [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = "voice-tty-full-headphones",
    130     [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = "voice-tty-vco-headphones",
    131     [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = "voice-tty-hco-handset",
    132 
    133     /* Capture sound devices */
    134     [SND_DEVICE_IN_HANDSET_MIC] = "handset-mic",
    135     [SND_DEVICE_IN_SPEAKER_MIC] = "speaker-mic",
    136     [SND_DEVICE_IN_HEADSET_MIC] = "headset-mic",
    137     [SND_DEVICE_IN_HANDSET_MIC_AEC] = "handset-mic",
    138     [SND_DEVICE_IN_SPEAKER_MIC_AEC] = "voice-speaker-mic",
    139     [SND_DEVICE_IN_HEADSET_MIC_AEC] = "headset-mic",
    140     [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "voice-speaker-mic",
    141     [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "voice-headset-mic",
    142     [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic",
    143     [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic",
    144     [SND_DEVICE_IN_BT_SCO_MIC_WB] = "bt-sco-mic-wb",
    145     [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic",
    146     [SND_DEVICE_IN_VOICE_DMIC_EF] = "voice-dmic-ef",
    147     [SND_DEVICE_IN_VOICE_DMIC_BS] = "voice-dmic-bs",
    148     [SND_DEVICE_IN_VOICE_DMIC_EF_TMUS] = "voice-dmic-ef-tmus",
    149     [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF] = "voice-speaker-dmic-ef",
    150     [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS] = "voice-speaker-dmic-bs",
    151     [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = "voice-tty-full-headset-mic",
    152     [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = "voice-tty-vco-handset-mic",
    153     [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = "voice-tty-hco-headset-mic",
    154     [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic",
    155     [SND_DEVICE_IN_VOICE_REC_DMIC_EF] = "voice-rec-dmic-ef",
    156     [SND_DEVICE_IN_VOICE_REC_DMIC_BS] = "voice-rec-dmic-bs",
    157     [SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE] = "voice-rec-dmic-ef-fluence",
    158     [SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE] = "voice-rec-dmic-bs-fluence",
    159 };
    160 
    161 /* ACDB IDs (audio DSP path configuration IDs) for each sound device */
    162 static const int acdb_device_table[SND_DEVICE_MAX] = {
    163     [SND_DEVICE_NONE] = -1,
    164     [SND_DEVICE_OUT_HANDSET] = 7,
    165     [SND_DEVICE_OUT_SPEAKER] = 14,
    166     [SND_DEVICE_OUT_SPEAKER_REVERSE] = 14,
    167     [SND_DEVICE_OUT_HEADPHONES] = 10,
    168     [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = 10,
    169     [SND_DEVICE_OUT_VOICE_SPEAKER] = 14,
    170     [SND_DEVICE_OUT_VOICE_HEADPHONES] = 10,
    171     [SND_DEVICE_OUT_HDMI] = 18,
    172     [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 14,
    173     [SND_DEVICE_OUT_BT_SCO] = 22,
    174     [SND_DEVICE_OUT_BT_SCO_WB] = 39,
    175     [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = 81,
    176     [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = 17,
    177     [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = 17,
    178     [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = 37,
    179 
    180     [SND_DEVICE_IN_HANDSET_MIC] = 4,
    181     [SND_DEVICE_IN_SPEAKER_MIC] = 4,
    182     [SND_DEVICE_IN_HEADSET_MIC] = 8,
    183     [SND_DEVICE_IN_HANDSET_MIC_AEC] = 40,
    184     [SND_DEVICE_IN_SPEAKER_MIC_AEC] = 42,
    185     [SND_DEVICE_IN_HEADSET_MIC_AEC] = 47,
    186     [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = 11,
    187     [SND_DEVICE_IN_VOICE_HEADSET_MIC] = 8,
    188     [SND_DEVICE_IN_HDMI_MIC] = 4,
    189     [SND_DEVICE_IN_BT_SCO_MIC] = 21,
    190     [SND_DEVICE_IN_BT_SCO_MIC_WB] = 38,
    191     [SND_DEVICE_IN_CAMCORDER_MIC] = 61,
    192     [SND_DEVICE_IN_VOICE_DMIC_EF] = 6,
    193     [SND_DEVICE_IN_VOICE_DMIC_BS] = 5,
    194     [SND_DEVICE_IN_VOICE_DMIC_EF_TMUS] = 91,
    195     [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF] = 13,
    196     [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS] = 12,
    197     [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = 16,
    198     [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = 36,
    199     [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = 16,
    200     [SND_DEVICE_IN_VOICE_REC_MIC] = 62,
    201     /* TODO: Update with proper acdb ids */
    202     [SND_DEVICE_IN_VOICE_REC_DMIC_EF] = 62,
    203     [SND_DEVICE_IN_VOICE_REC_DMIC_BS] = 62,
    204     [SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE] = 6,
    205     [SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE] = 5,
    206 };
    207 
    208 #define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL)
    209 #define LOW_LATENCY_PLATFORM_DELAY (13*1000LL)
    210 
    211 static pthread_once_t check_op_once_ctl = PTHREAD_ONCE_INIT;
    212 static bool is_tmus = false;
    213 
    214 static void check_operator()
    215 {
    216     char value[PROPERTY_VALUE_MAX];
    217     int mccmnc;
    218     property_get("gsm.sim.operator.numeric",value,"0");
    219     mccmnc = atoi(value);
    220     ALOGD("%s: tmus mccmnc %d", __func__, mccmnc);
    221     switch(mccmnc) {
    222     /* TMUS MCC(310), MNC(490, 260, 026) */
    223     case 310490:
    224     case 310260:
    225     case 310026:
    226         is_tmus = true;
    227         break;
    228     }
    229 }
    230 
    231 bool is_operator_tmus()
    232 {
    233     pthread_once(&check_op_once_ctl, check_operator);
    234     return is_tmus;
    235 }
    236 
    237 static int set_echo_reference(struct mixer *mixer, const char* ec_ref)
    238 {
    239     struct mixer_ctl *ctl;
    240     const char *mixer_ctl_name = "EC_REF_RX";
    241 
    242     ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
    243     if (!ctl) {
    244         ALOGE("%s: Could not get ctl for mixer cmd - %s",
    245               __func__, mixer_ctl_name);
    246         return -EINVAL;
    247     }
    248     ALOGV("Setting EC Reference: %s", ec_ref);
    249     mixer_ctl_set_enum_by_string(ctl, ec_ref);
    250     return 0;
    251 }
    252 
    253 void *platform_init(struct audio_device *adev)
    254 {
    255     char platform[PROPERTY_VALUE_MAX];
    256     char baseband[PROPERTY_VALUE_MAX];
    257     char value[PROPERTY_VALUE_MAX];
    258     struct platform_data *my_data;
    259 
    260     adev->mixer = mixer_open(MIXER_CARD);
    261 
    262     if (!adev->mixer) {
    263         ALOGE("Unable to open the mixer, aborting.");
    264         return NULL;
    265     }
    266 
    267     adev->audio_route = audio_route_init(MIXER_CARD, MIXER_XML_PATH);
    268     if (!adev->audio_route) {
    269         ALOGE("%s: Failed to init audio route controls, aborting.", __func__);
    270         return NULL;
    271     }
    272 
    273     my_data = calloc(1, sizeof(struct platform_data));
    274 
    275     my_data->adev = adev;
    276     my_data->dualmic_config = DUALMIC_CONFIG_NONE;
    277     my_data->fluence_in_spkr_mode = false;
    278     my_data->fluence_in_voice_call = false;
    279     my_data->fluence_in_voice_rec = false;
    280 
    281     property_get("persist.audio.dualmic.config",value,"");
    282     if (!strcmp("broadside", value)) {
    283         my_data->dualmic_config = DUALMIC_CONFIG_BROADSIDE;
    284         adev->acdb_settings |= DMIC_FLAG;
    285     } else if (!strcmp("endfire", value)) {
    286         my_data->dualmic_config = DUALMIC_CONFIG_ENDFIRE;
    287         adev->acdb_settings |= DMIC_FLAG;
    288     }
    289 
    290     if (my_data->dualmic_config != DUALMIC_CONFIG_NONE) {
    291         property_get("persist.audio.fluence.voicecall",value,"");
    292         if (!strcmp("true", value)) {
    293             my_data->fluence_in_voice_call = true;
    294         }
    295 
    296         property_get("persist.audio.fluence.voicerec",value,"");
    297         if (!strcmp("true", value)) {
    298             my_data->fluence_in_voice_rec = true;
    299         }
    300 
    301         property_get("persist.audio.fluence.speaker",value,"");
    302         if (!strcmp("true", value)) {
    303             my_data->fluence_in_spkr_mode = true;
    304         }
    305     }
    306 
    307     my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
    308     if (my_data->acdb_handle == NULL) {
    309         ALOGE("%s: DLOPEN failed for %s", __func__, LIB_ACDB_LOADER);
    310     } else {
    311         ALOGV("%s: DLOPEN successful for %s", __func__, LIB_ACDB_LOADER);
    312         my_data->acdb_deallocate = (acdb_deallocate_t)dlsym(my_data->acdb_handle,
    313                                                     "acdb_loader_deallocate_ACDB");
    314         my_data->acdb_send_audio_cal = (acdb_send_audio_cal_t)dlsym(my_data->acdb_handle,
    315                                                     "acdb_loader_send_audio_cal");
    316         if (!my_data->acdb_send_audio_cal)
    317             ALOGW("%s: Could not find the symbol acdb_send_audio_cal from %s",
    318                   __func__, LIB_ACDB_LOADER);
    319         my_data->acdb_send_voice_cal = (acdb_send_voice_cal_t)dlsym(my_data->acdb_handle,
    320                                                     "acdb_loader_send_voice_cal");
    321         my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
    322                                                     "acdb_loader_init_ACDB");
    323         if (my_data->acdb_init == NULL)
    324             ALOGE("%s: dlsym error %s for acdb_loader_init_ACDB", __func__, dlerror());
    325         else
    326             my_data->acdb_init();
    327     }
    328 
    329     /* If platform is Fusion3, load CSD Client specific symbols
    330      * Voice call is handled by MDM and apps processor talks to
    331      * MDM through CSD Client
    332      */
    333     property_get("ro.board.platform", platform, "");
    334     property_get("ro.baseband", baseband, "");
    335     if (!strcmp("msm8960", platform) && !strcmp("mdm", baseband)) {
    336         my_data->csd_client = dlopen(LIB_CSD_CLIENT, RTLD_NOW);
    337         if (my_data->csd_client == NULL)
    338             ALOGE("%s: DLOPEN failed for %s", __func__, LIB_CSD_CLIENT);
    339     }
    340 
    341     if (my_data->csd_client) {
    342         ALOGV("%s: DLOPEN successful for %s", __func__, LIB_CSD_CLIENT);
    343         my_data->csd_client_deinit = (csd_client_deinit_t)dlsym(my_data->csd_client,
    344                                                     "csd_client_deinit");
    345         my_data->csd_disable_device = (csd_disable_device_t)dlsym(my_data->csd_client,
    346                                                     "csd_client_disable_device");
    347         my_data->csd_enable_device = (csd_enable_device_t)dlsym(my_data->csd_client,
    348                                                     "csd_client_enable_device");
    349         my_data->csd_start_voice = (csd_start_voice_t)dlsym(my_data->csd_client,
    350                                                     "csd_client_start_voice");
    351         my_data->csd_stop_voice = (csd_stop_voice_t)dlsym(my_data->csd_client,
    352                                                     "csd_client_stop_voice");
    353         my_data->csd_volume = (csd_volume_t)dlsym(my_data->csd_client,
    354                                                     "csd_client_volume");
    355         my_data->csd_mic_mute = (csd_mic_mute_t)dlsym(my_data->csd_client,
    356                                                     "csd_client_mic_mute");
    357         my_data->csd_client_init = (csd_client_init_t)dlsym(my_data->csd_client,
    358                                                     "csd_client_init");
    359 
    360         if (my_data->csd_client_init == NULL) {
    361             ALOGE("%s: dlsym error %s for csd_client_init", __func__, dlerror());
    362         } else {
    363             my_data->csd_client_init();
    364         }
    365     }
    366 
    367     return my_data;
    368 }
    369 
    370 void platform_deinit(void *platform)
    371 {
    372     free(platform);
    373 }
    374 
    375 const char *platform_get_snd_device_name(snd_device_t snd_device)
    376 {
    377     if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX)
    378         return device_table[snd_device];
    379     else
    380         return "none";
    381 }
    382 
    383 void platform_add_backend_name(void *platform __unused, char *mixer_path,
    384                                snd_device_t snd_device)
    385 {
    386     if (snd_device == SND_DEVICE_IN_BT_SCO_MIC)
    387         strcat(mixer_path, " bt-sco");
    388     else if(snd_device == SND_DEVICE_OUT_BT_SCO)
    389         strcat(mixer_path, " bt-sco");
    390     else if (snd_device == SND_DEVICE_OUT_HDMI)
    391         strcat(mixer_path, " hdmi");
    392     else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HDMI)
    393         strcat(mixer_path, " speaker-and-hdmi");
    394     else if (snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
    395              snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB)
    396         strcat(mixer_path, " bt-sco-wb");
    397 }
    398 
    399 int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type)
    400 {
    401     int device_id;
    402     if (device_type == PCM_PLAYBACK)
    403         device_id = pcm_device_table[usecase][0];
    404     else
    405         device_id = pcm_device_table[usecase][1];
    406     return device_id;
    407 }
    408 
    409 int platform_get_snd_device_index(char *snd_device_index_name __unused)
    410 {
    411     return -ENODEV;
    412 }
    413 
    414 int platform_set_snd_device_acdb_id(snd_device_t snd_device __unused,
    415                                     unsigned int acdb_id __unused)
    416 {
    417     return -ENODEV;
    418 }
    419 
    420 int platform_get_snd_device_acdb_id(snd_device_t snd_device __unused)
    421 {
    422     ALOGE("%s: Not implemented", __func__);
    423     return -ENOSYS;
    424 }
    425 
    426 int platform_send_audio_calibration(void *platform, snd_device_t snd_device)
    427 {
    428     struct platform_data *my_data = (struct platform_data *)platform;
    429     int acdb_dev_id, acdb_dev_type;
    430 
    431     acdb_dev_id = acdb_device_table[snd_device];
    432     if (acdb_dev_id < 0) {
    433         ALOGE("%s: Could not find acdb id for device(%d)",
    434               __func__, snd_device);
    435         return -EINVAL;
    436     }
    437     if (my_data->acdb_send_audio_cal) {
    438         ("%s: sending audio calibration for snd_device(%d) acdb_id(%d)",
    439               __func__, snd_device, acdb_dev_id);
    440         if (snd_device >= SND_DEVICE_OUT_BEGIN &&
    441                 snd_device < SND_DEVICE_OUT_END)
    442             acdb_dev_type = ACDB_DEV_TYPE_OUT;
    443         else
    444             acdb_dev_type = ACDB_DEV_TYPE_IN;
    445         my_data->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type);
    446     }
    447     return 0;
    448 }
    449 
    450 int platform_switch_voice_call_device_pre(void *platform)
    451 {
    452     struct platform_data *my_data = (struct platform_data *)platform;
    453     int ret = 0;
    454 
    455     if (my_data->csd_client != NULL &&
    456         voice_is_in_call(my_data->adev)) {
    457         /* This must be called before disabling the mixer controls on APQ side */
    458         if (my_data->csd_disable_device == NULL) {
    459             ALOGE("%s: dlsym error for csd_disable_device", __func__);
    460         } else {
    461             ret = my_data->csd_disable_device();
    462             if (ret < 0) {
    463                 ALOGE("%s: csd_client_disable_device, failed, error %d",
    464                       __func__, ret);
    465             }
    466         }
    467     }
    468     return ret;
    469 }
    470 
    471 int platform_switch_voice_call_device_post(void *platform,
    472                                            snd_device_t out_snd_device,
    473                                            snd_device_t in_snd_device)
    474 {
    475     struct platform_data *my_data = (struct platform_data *)platform;
    476     int acdb_rx_id, acdb_tx_id;
    477     int ret = 0;
    478 
    479     if (my_data->csd_client) {
    480         if (my_data->csd_enable_device == NULL) {
    481             ALOGE("%s: dlsym error for csd_enable_device",
    482                   __func__);
    483         } else {
    484             acdb_rx_id = acdb_device_table[out_snd_device];
    485             acdb_tx_id = acdb_device_table[in_snd_device];
    486 
    487             if (acdb_rx_id > 0 || acdb_tx_id > 0) {
    488                 ret = my_data->csd_enable_device(acdb_rx_id, acdb_tx_id,
    489                                                     my_data->adev->acdb_settings);
    490                 if (ret < 0) {
    491                     ALOGE("%s: csd_enable_device, failed, error %d",
    492                           __func__, ret);
    493                 }
    494             } else {
    495                 ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__,
    496                       acdb_rx_id, acdb_tx_id);
    497             }
    498         }
    499     }
    500 
    501     return ret;
    502 }
    503 
    504 int platform_start_voice_call(void *platform, uint32_t vsid __unused)
    505 {
    506     struct platform_data *my_data = (struct platform_data *)platform;
    507     int ret = 0;
    508 
    509     if (my_data->csd_client) {
    510         if (my_data->csd_start_voice == NULL) {
    511             ALOGE("dlsym error for csd_client_start_voice");
    512             ret = -ENOSYS;
    513         } else {
    514             ret = my_data->csd_start_voice();
    515             if (ret < 0) {
    516                 ALOGE("%s: csd_start_voice error %d\n", __func__, ret);
    517             }
    518         }
    519     }
    520 
    521     return ret;
    522 }
    523 
    524 int platform_stop_voice_call(void *platform, uint32_t vsid __unused)
    525 {
    526     struct platform_data *my_data = (struct platform_data *)platform;
    527     int ret = 0;
    528 
    529     if (my_data->csd_client) {
    530         if (my_data->csd_stop_voice == NULL) {
    531             ALOGE("dlsym error for csd_stop_voice");
    532         } else {
    533             ret = my_data->csd_stop_voice();
    534             if (ret < 0) {
    535                 ALOGE("%s: csd_stop_voice error %d\n", __func__, ret);
    536             }
    537         }
    538     }
    539 
    540     return ret;
    541 }
    542 
    543 int platform_set_voice_volume(void *platform, int volume)
    544 {
    545     struct platform_data *my_data = (struct platform_data *)platform;
    546     int ret = 0;
    547 
    548     if (my_data->csd_client) {
    549         if (my_data->csd_volume == NULL) {
    550             ALOGE("%s: dlsym error for csd_volume", __func__);
    551         } else {
    552             ret = my_data->csd_volume(volume);
    553             if (ret < 0) {
    554                 ALOGE("%s: csd_volume error %d", __func__, ret);
    555             }
    556         }
    557     } else {
    558         ALOGE("%s: No CSD Client present", __func__);
    559     }
    560 
    561     return ret;
    562 }
    563 
    564 int platform_set_mic_mute(void *platform, bool state)
    565 {
    566     struct platform_data *my_data = (struct platform_data *)platform;
    567     int ret = 0;
    568 
    569     if (my_data->adev->mode == AUDIO_MODE_IN_CALL) {
    570         if (my_data->csd_client) {
    571             if (my_data->csd_mic_mute == NULL) {
    572                 ALOGE("%s: dlsym error for csd_mic_mute", __func__);
    573             } else {
    574                 ret = my_data->csd_mic_mute(state);
    575                 if (ret < 0) {
    576                     ALOGE("%s: csd_mic_mute error %d", __func__, ret);
    577                 }
    578             }
    579         } else {
    580             ALOGE("%s: No CSD Client present", __func__);
    581         }
    582     }
    583 
    584     return ret;
    585 }
    586 
    587 int platform_set_device_mute(void *platform __unused, bool state __unused, char *dir __unused)
    588 {
    589     ALOGE("%s: Not implemented", __func__);
    590     return -ENOSYS;
    591 }
    592 
    593 snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices)
    594 {
    595     struct platform_data *my_data = (struct platform_data *)platform;
    596     struct audio_device *adev = my_data->adev;
    597     audio_mode_t mode = adev->mode;
    598     snd_device_t snd_device = SND_DEVICE_NONE;
    599 
    600     ALOGV("%s: enter: output devices(%#x)", __func__, devices);
    601     if (devices == AUDIO_DEVICE_NONE ||
    602         devices & AUDIO_DEVICE_BIT_IN) {
    603         ALOGV("%s: Invalid output devices (%#x)", __func__, devices);
    604         goto exit;
    605     }
    606 
    607     if (voice_is_in_call(adev)) {
    608         if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
    609             devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
    610             if (adev->voice.tty_mode == TTY_MODE_FULL)
    611                 snd_device = SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES;
    612             else if (adev->voice.tty_mode == TTY_MODE_VCO)
    613                 snd_device = SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES;
    614             else if (adev->voice.tty_mode == TTY_MODE_HCO)
    615                 snd_device = SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET;
    616             else
    617                 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES;
    618         } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
    619             if (adev->bt_wb_speech_enabled) {
    620                 snd_device = SND_DEVICE_OUT_BT_SCO_WB;
    621             } else {
    622                 snd_device = SND_DEVICE_OUT_BT_SCO;
    623             }
    624         } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
    625             snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
    626         } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
    627             if (is_operator_tmus())
    628                 snd_device = SND_DEVICE_OUT_VOICE_HANDSET_TMUS;
    629             else
    630                 snd_device = SND_DEVICE_OUT_HANDSET;
    631         }
    632         if (snd_device != SND_DEVICE_NONE) {
    633             goto exit;
    634         }
    635     }
    636 
    637     if (popcount(devices) == 2) {
    638         if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
    639                         AUDIO_DEVICE_OUT_SPEAKER)) {
    640             snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
    641         } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
    642                                AUDIO_DEVICE_OUT_SPEAKER)) {
    643             snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
    644         } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL |
    645                                AUDIO_DEVICE_OUT_SPEAKER)) {
    646             snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
    647         } else {
    648             ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
    649             goto exit;
    650         }
    651         if (snd_device != SND_DEVICE_NONE) {
    652             goto exit;
    653         }
    654     }
    655 
    656     if (popcount(devices) != 1) {
    657         ALOGE("%s: Invalid output devices(%#x)", __func__, devices);
    658         goto exit;
    659     }
    660 
    661     if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
    662         devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
    663         snd_device = SND_DEVICE_OUT_HEADPHONES;
    664     } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
    665         if (my_data->speaker_lr_swap)
    666             snd_device = SND_DEVICE_OUT_SPEAKER_REVERSE;
    667         else
    668             snd_device = SND_DEVICE_OUT_SPEAKER;
    669     } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
    670         if (adev->bt_wb_speech_enabled) {
    671             snd_device = SND_DEVICE_OUT_BT_SCO_WB;
    672         } else {
    673             snd_device = SND_DEVICE_OUT_BT_SCO;
    674         }
    675     } else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
    676         snd_device = SND_DEVICE_OUT_HDMI ;
    677     } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
    678         snd_device = SND_DEVICE_OUT_HANDSET;
    679     } else {
    680         ALOGE("%s: Unknown device(s) %#x", __func__, devices);
    681     }
    682 exit:
    683     ALOGV("%s: exit: snd_device(%s)", __func__, device_table[snd_device]);
    684     return snd_device;
    685 }
    686 
    687 snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device)
    688 {
    689     struct platform_data *my_data = (struct platform_data *)platform;
    690     struct audio_device *adev = my_data->adev;
    691     audio_source_t  source = (adev->active_input == NULL) ?
    692                                 AUDIO_SOURCE_DEFAULT : adev->active_input->source;
    693 
    694     audio_mode_t    mode   = adev->mode;
    695     audio_devices_t in_device = ((adev->active_input == NULL) ?
    696                                     AUDIO_DEVICE_NONE : adev->active_input->device)
    697                                 & ~AUDIO_DEVICE_BIT_IN;
    698     audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
    699                                 AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
    700     snd_device_t snd_device = SND_DEVICE_NONE;
    701 
    702     ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
    703           __func__, out_device, in_device);
    704     if ((out_device != AUDIO_DEVICE_NONE) && voice_is_in_call(adev)) {
    705         if (adev->voice.tty_mode != TTY_MODE_OFF) {
    706             if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
    707                 out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
    708                 switch (adev->voice.tty_mode) {
    709                 case TTY_MODE_FULL:
    710                     snd_device = SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC;
    711                     break;
    712                 case TTY_MODE_VCO:
    713                     snd_device = SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC;
    714                     break;
    715                 case TTY_MODE_HCO:
    716                     snd_device = SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC;
    717                     break;
    718                 default:
    719                     ALOGE("%s: Invalid TTY mode (%#x)", __func__, adev->voice.tty_mode);
    720                 }
    721                 goto exit;
    722             }
    723         }
    724         if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
    725             out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
    726             if (my_data->fluence_in_voice_call == false) {
    727                 snd_device = SND_DEVICE_IN_HANDSET_MIC;
    728             } else {
    729                 if (my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
    730                     if (is_operator_tmus())
    731                         snd_device = SND_DEVICE_IN_VOICE_DMIC_EF_TMUS;
    732                     else
    733                         snd_device = SND_DEVICE_IN_VOICE_DMIC_EF;
    734                 } else if(my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE)
    735                     snd_device = SND_DEVICE_IN_VOICE_DMIC_BS;
    736                 else
    737                     snd_device = SND_DEVICE_IN_HANDSET_MIC;
    738             }
    739         } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
    740             snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
    741         } else if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
    742             if (adev->bt_wb_speech_enabled) {
    743                 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
    744             } else {
    745                 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
    746             }
    747         } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
    748             if (my_data->fluence_in_voice_call && my_data->fluence_in_spkr_mode &&
    749                     my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
    750                 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF;
    751             } else if (my_data->fluence_in_voice_call && my_data->fluence_in_spkr_mode &&
    752                     my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE) {
    753                 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS;
    754             } else {
    755                 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
    756             }
    757         }
    758     } else if (source == AUDIO_SOURCE_CAMCORDER) {
    759         if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
    760             in_device & AUDIO_DEVICE_IN_BACK_MIC) {
    761             snd_device = SND_DEVICE_IN_CAMCORDER_MIC;
    762         }
    763     } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) {
    764         if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
    765             if (my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
    766                 if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
    767                     snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_EF;
    768                 else if (my_data->fluence_in_voice_rec)
    769                     snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE;
    770             } else if (my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE) {
    771                 if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
    772                     snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_BS;
    773                 else if (my_data->fluence_in_voice_rec)
    774                     snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE;
    775             }
    776 
    777             if (snd_device == SND_DEVICE_NONE) {
    778                 snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
    779             }
    780         }
    781     } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
    782         if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
    783             in_device = AUDIO_DEVICE_IN_BACK_MIC;
    784         if (adev->active_input) {
    785             if (adev->active_input->enable_aec) {
    786                 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
    787                     snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
    788                 } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
    789                     snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
    790                 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
    791                     snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
    792                 }
    793                 set_echo_reference(adev->mixer, "SLIM_RX");
    794             } else
    795                 set_echo_reference(adev->mixer, "NONE");
    796         }
    797     } else if (source == AUDIO_SOURCE_DEFAULT) {
    798         goto exit;
    799     }
    800 
    801 
    802     if (snd_device != SND_DEVICE_NONE) {
    803         goto exit;
    804     }
    805 
    806     if (in_device != AUDIO_DEVICE_NONE &&
    807             !(in_device & AUDIO_DEVICE_IN_VOICE_CALL) &&
    808             !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) {
    809         if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
    810             snd_device = SND_DEVICE_IN_HANDSET_MIC;
    811         } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
    812             snd_device = SND_DEVICE_IN_SPEAKER_MIC;
    813         } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
    814             snd_device = SND_DEVICE_IN_HEADSET_MIC;
    815         } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
    816             if (adev->bt_wb_speech_enabled) {
    817                 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
    818             } else {
    819                 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
    820             }
    821         } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) {
    822             snd_device = SND_DEVICE_IN_HDMI_MIC;
    823         } else {
    824             ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
    825             ALOGW("%s: Using default handset-mic", __func__);
    826             snd_device = SND_DEVICE_IN_HANDSET_MIC;
    827         }
    828     } else {
    829         if (out_device & AUDIO_DEVICE_OUT_EARPIECE) {
    830             snd_device = SND_DEVICE_IN_HANDSET_MIC;
    831         } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
    832             snd_device = SND_DEVICE_IN_HEADSET_MIC;
    833         } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
    834             snd_device = SND_DEVICE_IN_SPEAKER_MIC;
    835         } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
    836             snd_device = SND_DEVICE_IN_HANDSET_MIC;
    837         } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
    838             if (adev->bt_wb_speech_enabled) {
    839                 snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
    840             } else {
    841                 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
    842             }
    843         } else if (out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
    844             snd_device = SND_DEVICE_IN_HDMI_MIC;
    845         } else {
    846             ALOGE("%s: Unknown output device(s) %#x", __func__, out_device);
    847             ALOGW("%s: Using default handset-mic", __func__);
    848             snd_device = SND_DEVICE_IN_HANDSET_MIC;
    849         }
    850     }
    851 exit:
    852     ALOGV("%s: exit: in_snd_device(%s)", __func__, device_table[snd_device]);
    853     return snd_device;
    854 }
    855 
    856 int platform_set_hdmi_channels(void *platform,  int channel_count)
    857 {
    858     struct platform_data *my_data = (struct platform_data *)platform;
    859     struct audio_device *adev = my_data->adev;
    860     struct mixer_ctl *ctl;
    861     const char *channel_cnt_str = NULL;
    862     const char *mixer_ctl_name = "HDMI_RX Channels";
    863     switch (channel_count) {
    864     case 8:
    865         channel_cnt_str = "Eight"; break;
    866     case 7:
    867         channel_cnt_str = "Seven"; break;
    868     case 6:
    869         channel_cnt_str = "Six"; break;
    870     case 5:
    871         channel_cnt_str = "Five"; break;
    872     case 4:
    873         channel_cnt_str = "Four"; break;
    874     case 3:
    875         channel_cnt_str = "Three"; break;
    876     default:
    877         channel_cnt_str = "Two"; break;
    878     }
    879     ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
    880     if (!ctl) {
    881         ALOGE("%s: Could not get ctl for mixer cmd - %s",
    882               __func__, mixer_ctl_name);
    883         return -EINVAL;
    884     }
    885     ALOGV("HDMI channel count: %s", channel_cnt_str);
    886     mixer_ctl_set_enum_by_string(ctl, channel_cnt_str);
    887     return 0;
    888 }
    889 
    890 int platform_edid_get_max_channels(void *platform __unused)
    891 {
    892     FILE *file;
    893     struct audio_block_header header;
    894     char block[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE];
    895     char *sad = block;
    896     int num_audio_blocks;
    897     int channel_count;
    898     int max_channels = 0;
    899     int i;
    900 
    901     file = fopen(AUDIO_DATA_BLOCK_PATH, "rb");
    902     if (file == NULL) {
    903         ALOGE("Unable to open '%s'", AUDIO_DATA_BLOCK_PATH);
    904         return 0;
    905     }
    906 
    907     /* Read audio block header */
    908     fread(&header, 1, sizeof(header), file);
    909 
    910     /* Read SAD blocks, clamping the maximum size for safety */
    911     if (header.length > (int)sizeof(block))
    912         header.length = (int)sizeof(block);
    913     fread(&block, header.length, 1, file);
    914 
    915     fclose(file);
    916 
    917     /* Calculate the number of SAD blocks */
    918     num_audio_blocks = header.length / SAD_BLOCK_SIZE;
    919 
    920     for (i = 0; i < num_audio_blocks; i++) {
    921         /* Only consider LPCM blocks */
    922         if ((sad[0] >> 3) != EDID_FORMAT_LPCM)
    923             continue;
    924 
    925         channel_count = (sad[0] & 0x7) + 1;
    926         if (channel_count > max_channels)
    927             max_channels = channel_count;
    928 
    929         /* Advance to next block */
    930         sad += 3;
    931     }
    932 
    933     return max_channels;
    934 }
    935 
    936 int platform_set_incall_recording_session_id(void *platform __unused,
    937                                              uint32_t session_id __unused, int rec_mode __unused)
    938 {
    939     ALOGE("%s: Not implemented", __func__);
    940     return -ENOSYS;
    941 }
    942 
    943 int platform_stop_incall_recording_usecase(void *platform __unused)
    944 {
    945     ALOGE("%s: Not implemented", __func__);
    946     return -ENOSYS;
    947 }
    948 
    949 int platform_start_incall_music_usecase(void *platform __unused)
    950 {
    951     ALOGE("%s: Not implemented", __func__);
    952     return -ENOSYS;
    953 }
    954 
    955 int platform_stop_incall_music_usecase(void *platform __unused)
    956 {
    957     ALOGE("%s: Not implemented", __func__);
    958     return -ENOSYS;
    959 }
    960 
    961 int platform_set_parameters(void *platform __unused,
    962                             struct str_parms *parms __unused)
    963 {
    964     ALOGE("%s: Not implemented", __func__);
    965     return -ENOSYS;
    966 }
    967 
    968 /* Delay in Us */
    969 int64_t platform_render_latency(audio_usecase_t usecase)
    970 {
    971     switch (usecase) {
    972         case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER:
    973             return DEEP_BUFFER_PLATFORM_DELAY;
    974         case USECASE_AUDIO_PLAYBACK_LOW_LATENCY:
    975             return LOW_LATENCY_PLATFORM_DELAY;
    976         default:
    977             return 0;
    978     }
    979 }
    980 
    981 int platform_switch_voice_call_enable_device_config(void *platform __unused,
    982                                                     snd_device_t out_snd_device __unused,
    983                                                     snd_device_t in_snd_device __unused)
    984 {
    985     return 0;
    986 }
    987 
    988 int platform_switch_voice_call_usecase_route_post(void *platform __unused,
    989                                                   snd_device_t out_snd_device __unused,
    990                                                   snd_device_t in_snd_device __unused)
    991 {
    992     return 0;
    993 }
    994 
    995 int platform_get_sample_rate(void *platform __unused, uint32_t *rate __unused)
    996 {
    997     return -ENOSYS;
    998 }
    999 
   1000 int platform_get_usecase_index(const char * usecase __unused)
   1001 {
   1002     return -ENOSYS;
   1003 }
   1004 
   1005 int platform_set_usecase_pcm_id(audio_usecase_t usecase __unused, int32_t type __unused,
   1006                                 int32_t pcm_id __unused)
   1007 {
   1008     return -ENOSYS;
   1009 }
   1010 
   1011 int platform_set_snd_device_backend(snd_device_t device __unused,
   1012                                     const char *backend __unused,
   1013                                     const char *hw_interface __unused)
   1014 {
   1015     return -ENOSYS;
   1016 }
   1017 
   1018 void platform_set_echo_reference(struct audio_device *adev __unused,
   1019                                  bool enable __unused,
   1020                                  audio_devices_t out_device __unused)
   1021 {
   1022     return;
   1023 }
   1024 
   1025 int platform_swap_lr_channels(struct audio_device *adev, bool swap_channels)
   1026 {
   1027     // only update the selected device if there is active pcm playback
   1028     struct audio_usecase *usecase;
   1029     struct listnode *node;
   1030     struct platform_data *my_data = (struct platform_data *)adev->platform;
   1031     int status = 0;
   1032 
   1033     if (my_data->speaker_lr_swap != swap_channels) {
   1034         my_data->speaker_lr_swap = swap_channels;
   1035 
   1036         list_for_each(node, &adev->usecase_list) {
   1037             usecase = node_to_item(node, struct audio_usecase, list);
   1038             if (usecase->type == PCM_PLAYBACK &&
   1039                 usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
   1040                 const char *mixer_path;
   1041                 if (swap_channels) {
   1042                     mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER_REVERSE);
   1043                     audio_route_apply_and_update_path(adev->audio_route, mixer_path);
   1044                 } else {
   1045                     mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER);
   1046                     audio_route_apply_and_update_path(adev->audio_route, mixer_path);
   1047                 }
   1048                 break;
   1049             }
   1050         }
   1051     }
   1052     return status;
   1053 }
   1054 
   1055 bool platform_send_gain_dep_cal(void *platform __unused,
   1056                                 int level __unused)
   1057 {
   1058     return 0;
   1059 }
   1060 
   1061 bool platform_can_split_snd_device(snd_device_t in_snd_device __unused,
   1062                                    int *num_devices __unused,
   1063                                    snd_device_t *out_snd_devices __unused)
   1064 {
   1065     return false;
   1066 }
   1067 
   1068 bool platform_check_backends_match(snd_device_t snd_device1 __unused,
   1069                                    snd_device_t snd_device2 __unused)
   1070 {
   1071     return true;
   1072 }
   1073