| /* |
| * Copyright (C) 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #define LOG_TAG "hardware_cal" |
| /*#define LOG_NDEBUG 0*/ |
| #define LOG_NDDEBUG 0 |
| |
| #ifdef HWDEP_CAL_ENABLED |
| |
| #include <stdlib.h> |
| #include <dlfcn.h> |
| #include <fcntl.h> |
| #include <sys/ioctl.h> |
| #include <unistd.h> |
| #include <log/log.h> |
| #include <audio_hw.h> |
| #include "audio_extn.h" |
| #include "sound/msmcal-hwdep.h" |
| |
| #define SOUND_TRIGGER_DEVICE_HANDSET_MONO_LOW_POWER_ACDB_ID (100) |
| #define MAX_CAL_NAME 20 |
| |
| typedef struct acdb_audio_cal_cfg { |
| uint32_t persist; |
| uint32_t snd_dev_id; |
| audio_devices_t dev_id; |
| int32_t acdb_dev_id; |
| uint32_t app_type; |
| uint32_t topo_id; |
| uint32_t sampling_rate; |
| uint32_t cal_type; |
| uint32_t module_id; |
| uint32_t param_id; |
| } acdb_audio_cal_cfg_t; |
| |
| struct param_data { |
| int use_case; |
| int acdb_id; |
| int get_size; |
| int buff_size; |
| int data_size; |
| void *buff; |
| }; |
| |
| char cal_name_info[WCD9XXX_MAX_CAL][MAX_CAL_NAME] = { |
| [WCD9XXX_ANC_CAL] = "anc_cal", |
| [WCD9XXX_MBHC_CAL] = "mbhc_cal", |
| [WCD9XXX_MAD_CAL] = "mad_cal", |
| }; |
| |
| typedef int (*acdb_get_calibration_t)(char *attr, int size, void *data); |
| acdb_get_calibration_t acdb_get_calibration; |
| |
| static int hw_util_open(int card_no) |
| { |
| int fd = -1; |
| char dev_name[256]; |
| |
| snprintf(dev_name, sizeof(dev_name), "/dev/snd/hwC%uD%u", |
| card_no, WCD9XXX_CODEC_HWDEP_NODE); |
| ALOGD("%s: Opening device %s\n", __func__, dev_name); |
| fd = open(dev_name, O_WRONLY); |
| if (fd < 0) { |
| ALOGE("%s: cannot open device '%s'\n", __func__, dev_name); |
| return fd; |
| } |
| ALOGD("%s: success", __func__); |
| return fd; |
| } |
| |
| static int send_codec_cal(acdb_get_calibration_t acdb_loader_get_calibration, int fd) |
| { |
| int ret = 0, type; |
| |
| for (type = WCD9XXX_ANC_CAL; type < WCD9XXX_MAX_CAL; type++) { |
| struct wcdcal_ioctl_buffer codec_buffer; |
| struct param_data calib; |
| |
| if (!strcmp(cal_name_info[type], "mad_cal")) |
| calib.acdb_id = SOUND_TRIGGER_DEVICE_HANDSET_MONO_LOW_POWER_ACDB_ID; |
| calib.get_size = 1; |
| ret = acdb_loader_get_calibration(cal_name_info[type], sizeof(struct param_data), |
| &calib); |
| if (ret < 0) { |
| ALOGE("%s get_calibration failed\n", __func__); |
| return ret; |
| } |
| calib.get_size = 0; |
| calib.buff = malloc(calib.buff_size); |
| ret = acdb_loader_get_calibration(cal_name_info[type], |
| sizeof(struct param_data), &calib); |
| if (ret < 0) { |
| ALOGE("%s get_calibration failed\n", __func__); |
| free(calib.buff); |
| return ret; |
| } |
| codec_buffer.buffer = calib.buff; |
| codec_buffer.size = calib.data_size; |
| codec_buffer.cal_type = type; |
| if (ioctl(fd, SNDRV_CTL_IOCTL_HWDEP_CAL_TYPE, &codec_buffer) < 0) |
| ALOGE("Failed to call ioctl for %s err=%d", |
| cal_name_info[type], errno); |
| ALOGD("%s cal sent for %s", __func__, cal_name_info[type]); |
| free(calib.buff); |
| } |
| return ret; |
| } |
| |
| |
| void audio_extn_hwdep_cal_send(int snd_card, void *acdb_handle) |
| { |
| int fd; |
| |
| fd = hw_util_open(snd_card); |
| if (fd == -1) { |
| ALOGE("%s error open\n", __func__); |
| return; |
| } |
| |
| acdb_get_calibration = (acdb_get_calibration_t) |
| dlsym(acdb_handle, "acdb_loader_get_calibration"); |
| |
| if (acdb_get_calibration == NULL) { |
| ALOGE("%s: ERROR. dlsym Error:%s acdb_loader_get_calibration", __func__, |
| dlerror()); |
| return; |
| } |
| if (send_codec_cal(acdb_get_calibration, fd) < 0) |
| ALOGE("%s: Could not send anc cal", __FUNCTION__); |
| |
| close(fd); |
| } |
| |
| #endif |