10fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta/*
20fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta * Copyright (C) 2017 The Android Open Source Project
30fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta *
40fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta * Licensed under the Apache License, Version 2.0 (the "License");
50fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta * you may not use this file except in compliance with the License.
60fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta * You may obtain a copy of the License at
70fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta *
80fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta *      http://www.apache.org/licenses/LICENSE-2.0
90fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta *
100fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta * Unless required by applicable law or agreed to in writing, software
110fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta * distributed under the License is distributed on an "AS IS" BASIS,
120fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta * See the License for the specific language governing permissions and
140fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta * limitations under the License.
150fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta */
160fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
170fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta#define LOG_TAG "audio_hw_acdb"
180fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta//#define LOG_NDEBUG 0
190fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta#define LOG_NDDEBUG 0
200fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
21e4bd8251022572579bb5c844f4efdbe67abacbbaDan Albert#include <errno.h>
220fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta#include <stdlib.h>
230fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta#include <stdbool.h>
240fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta#include <dlfcn.h>
25e6e2d441c567d5da185b787d6c10ca2c8b36a694Haynes Mathew George#include <log/log.h>
260fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta#include <cutils/str_parms.h>
270fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta#include <system/audio.h>
280fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta#include <tinyalsa/asoundlib.h>
290fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta#include "acdb.h"
300fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta#include <platform_api.h>
310fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
320fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta#define PLATFORM_CONFIG_KEY_SOUNDCARD_NAME "snd_card_name"
330fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
340fb113194399805a0fdbf5bb3f812e98047272bdvivek mehtaint acdb_init(int snd_card_num)
350fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta{
360fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
370fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    int result = -1;
380fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    char *cvd_version = NULL;
390fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
400fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    char *snd_card_name = NULL;
410fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    struct mixer *mixer = NULL;
420fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    struct acdb_platform_data *my_data = NULL;
430fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
440fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    if(snd_card_num < 0) {
450fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        ALOGE("invalid sound card number");
460fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        return result;
470fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    }
480fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
490fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    mixer = mixer_open(snd_card_num);
500fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    if (!mixer) {
510fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        ALOGE("%s: Unable to open the mixer card: %d", __func__,
520fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta               snd_card_num);
530fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        goto cleanup;
540fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    }
550fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
560fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    my_data = calloc(1, sizeof(struct acdb_platform_data));
570fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    if (!my_data) {
580fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        ALOGE("failed to allocate acdb platform data");
590fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        goto cleanup;
600fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    }
610fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
620fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    list_init(&my_data->acdb_meta_key_list);
630fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
640fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
650fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    if (my_data->acdb_handle == NULL) {
660fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        ALOGE("%s: DLOPEN failed for %s", __func__, LIB_ACDB_LOADER);
670fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        goto cleanup;
680fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    }
690fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
700fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    ALOGV("%s: DLOPEN successful for %s", __func__, LIB_ACDB_LOADER);
710fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
720fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    my_data->acdb_init_v3 = (acdb_init_v3_t)dlsym(my_data->acdb_handle,
730fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta                                                     "acdb_loader_init_v3");
740fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    if (my_data->acdb_init_v3 == NULL)
750fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        ALOGE("%s: dlsym error %s for acdb_loader_init_v3", __func__, dlerror());
760fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
770fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    my_data->acdb_init_v2 = (acdb_init_v2_cvd_t)dlsym(my_data->acdb_handle,
780fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta                                                     "acdb_loader_init_v2");
790fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    if (my_data->acdb_init_v2 == NULL)
800fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        ALOGE("%s: dlsym error %s for acdb_loader_init_v2", __func__, dlerror());
810fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
820fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
830fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta                                                 "acdb_loader_init_ACDB");
840fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    if (my_data->acdb_init == NULL && my_data->acdb_init_v2 == NULL
850fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        && my_data->acdb_init_v3 == NULL) {
860fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        ALOGE("%s: dlsym error %s for acdb_loader_init_ACDB", __func__, dlerror());
870fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        goto cleanup;
880fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    }
890fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
900fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    /* Get CVD version */
910fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    cvd_version = calloc(1, MAX_CVD_VERSION_STRING_SIZE);
920fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    if (!cvd_version) {
930fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        ALOGE("%s: Failed to allocate cvd version", __func__);
940fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        goto cleanup;
950fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    } else {
960fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        struct mixer_ctl *ctl = NULL;
970fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        int count = 0;
980fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
990fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        ctl = mixer_get_ctl_by_name(mixer, CVD_VERSION_MIXER_CTL);
1000fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        if (!ctl) {
1010fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta            ALOGE("%s: Could not get ctl for mixer cmd - %s",  __func__, CVD_VERSION_MIXER_CTL);
1020fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta            goto cleanup;
1030fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        }
1040fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        mixer_ctl_update(ctl);
1050fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
1060fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        count = mixer_ctl_get_num_values(ctl);
1070fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        if (count > MAX_CVD_VERSION_STRING_SIZE)
1080fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta            count = MAX_CVD_VERSION_STRING_SIZE;
1090fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
1100fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        result = mixer_ctl_get_array(ctl, cvd_version, count);
1110fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        if (result != 0) {
1120fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta            ALOGE("%s: ERROR! mixer_ctl_get_array() failed to get CVD Version", __func__);
1130fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta            goto cleanup;
1140fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        }
1150fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    }
1160fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
1170fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    /* Get Sound card name */
1180fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    snd_card_name = strdup(mixer_get_name(mixer));
1190fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    if (!snd_card_name) {
1200fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        ALOGE("failed to allocate memory for snd_card_name");
1210fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        result = -1;
1220fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        goto cleanup;
1230fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    }
1240fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
1251ffb5b2d2b700ab85b2b4122c938bd9152246241vivek mehta    if (my_data->acdb_init_v3)
1260fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        result = my_data->acdb_init_v3(snd_card_name, cvd_version,
1270fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta                                       &my_data->acdb_meta_key_list);
1281ffb5b2d2b700ab85b2b4122c938bd9152246241vivek mehta    else if (my_data->acdb_init_v2)
1291ffb5b2d2b700ab85b2b4122c938bd9152246241vivek mehta        result = my_data->acdb_init_v2(snd_card_name, cvd_version, 0);
1301ffb5b2d2b700ab85b2b4122c938bd9152246241vivek mehta    else
1310fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        result = my_data->acdb_init();
1320fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
1330fb113194399805a0fdbf5bb3f812e98047272bdvivek mehtacleanup:
1340fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    if (NULL != my_data) {
1350fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        if (my_data->acdb_handle)
1360fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta            dlclose(my_data->acdb_handle);
1370fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
1380fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        struct listnode *node;
1390fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        struct meta_key_list *key_info;
1400fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        list_for_each(node, &my_data->acdb_meta_key_list) {
1410fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta            key_info = node_to_item(node, struct meta_key_list, list);
1420fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta            free(key_info);
1430fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        }
1440fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        free(my_data);
1450fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    }
1460fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
1470fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    mixer_close(mixer);
1480fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    free(cvd_version);
1490fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    free(snd_card_name);
1500fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
1510fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    return result;
1520fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta}
1530fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
1540fb113194399805a0fdbf5bb3f812e98047272bdvivek mehtaint acdb_set_parameters(void *platform, struct str_parms *parms)
1550fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta{
1560fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    struct acdb_platform_data *my_data = (struct acdb_platform_data *)platform;
1570fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    char value[128];
1580fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    char *kv_pairs = str_parms_to_str(parms);
1590fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    int ret = 0;
1600fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
1610fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    if (kv_pairs == NULL) {
1620fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        ret = -EINVAL;
1630fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        ALOGE("%s: key-value pair is NULL",__func__);
1640fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        goto done;
1650fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    }
1660fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
1670fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    ret = str_parms_get_str(parms, PLATFORM_CONFIG_KEY_SOUNDCARD_NAME,
1680fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta                            value, sizeof(value));
1690fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    if (ret >= 0) {
1700fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        str_parms_del(parms, PLATFORM_CONFIG_KEY_SOUNDCARD_NAME);
1710fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        my_data->snd_card_name = strdup(value);
1720fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        ALOGV("%s: sound card name %s", __func__, my_data->snd_card_name);
1730fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    }
1740fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
1750fb113194399805a0fdbf5bb3f812e98047272bdvivek mehtadone:
1760fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    free(kv_pairs);
1770fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
1780fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    return ret;
1790fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta}
180