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