hal: Add open source HAL for Elliptic Ultrasound
Author: Balázs Triszka <balika011@gmail.com>
Date: Thu May 11 03:19:29 2017 +0200
msm8998: ultrasound: Initial open source hal for Elliptic Ultrasound
* Needed for proximity sensor on Xiaomi Mi MIX
[Arasthel]: Change PCM id for Mi MIX 2 implementation
Change-Id: Iaef2266bc1b853d7a9d1e2a906014c6c91019d5f
Signed-off-by: Balázs Triszka <balika011@gmail.com>
Author: Michael Bestas <mkbestas@lineageos.org>
Date: Sat Feb 10 00:28:00 2018 +0200
msm8998: ultrasound: Remove unused code
* Params ultrasound_set_manual_calibration and ultrasound_set_sensitivity
do not exist.
Change-Id: I0004949db19b6ab7d49f20e422984e06a970cfe9
Author: Demon Singur <demonsingur@gmail.com>
Date: Sat Apr 21 09:08:03 2018 +0000
msm8998: hal: Update ultrasound route hacks
Change-Id: If002503dfba0f005f73a4455d68bbcce9d2f617e
Change-Id: I119316f264afbda9faf24950edfbca3891aa9769
Author: Vol Zhdanov <wight554@gmail.com>
Date: Fri Feb 1 02:16:26 2019 +0000
hal: fix channels swap for elliptic ultrasound devices
Change-Id: Id45b075c4ad098c95fcb617da10c56d38565b9c8
Change-Id: Icb18f5b41483d33188be103e13b6c915b6e681b8
diff --git a/hal/audio_extn/ultrasound.c b/hal/audio_extn/ultrasound.c
new file mode 100644
index 0000000..1199e22
--- /dev/null
+++ b/hal/audio_extn/ultrasound.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2017-2018 The LineageOS Project
+ * Copyright (c) 2017 Balázs Triszka <balika011@protonmail.ch>
+ *
+ * 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 "ultrasound"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <cutils/log.h>
+#include "audio_hw.h"
+#include "platform_api.h"
+#include <platform.h>
+#include "ultrasound.h"
+
+#define ULTRASOUND_CALIBRATION_FILE "/persist/audio/us_cal"
+#define ULTRASOUND_CALIBRATION_MIXER "Ultrasound Calibration Data"
+
+enum {
+ ULTRASOUND_STATUS_DEFAULT,
+ ULTRASOUND_STATUS_STARTED,
+ ULTRASOUND_STATUS_STOPPED,
+};
+
+struct pcm_config pcm_config_us = {
+ .channels = 1,
+ .rate = 96000,
+ .period_size = 1024,
+ .period_count = 2,
+ .format = PCM_FORMAT_S16_LE,
+};
+
+struct ultrasound_device {
+ struct pcm *rx_pcm, *tx_pcm;
+ int state;
+ struct audio_device *adev;
+};
+
+static struct ultrasound_device *us = NULL;
+
+void us_cal_load(void)
+{
+ FILE *f;
+ char buff[5] = {0}, us_cal[64];
+ struct mixer_ctl * ctl;
+ int rc;
+
+ f = fopen(ULTRASOUND_CALIBRATION_FILE, "r");
+ if (!f) {
+ ALOGE("%s: Cannot open calibration file: %s",
+ __func__, ULTRASOUND_CALIBRATION_FILE);
+ return;
+ }
+
+ for (size_t i = 0; i < sizeof(us_cal); i++) {
+ fread(buff, 1, sizeof(buff), f);
+ us_cal[i] = strtol(buff, 0, 16);
+ }
+ fclose(f);
+
+ ctl = mixer_get_ctl_by_name(us->adev->mixer, ULTRASOUND_CALIBRATION_MIXER);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",
+ __func__, ULTRASOUND_CALIBRATION_MIXER);
+ return;
+ }
+
+ rc = mixer_ctl_set_array(ctl, us_cal, sizeof(us_cal));
+ if (rc < 0)
+ ALOGE("%s: Could not set ctl, error:%d ", __func__, rc);
+}
+
+int us_init(struct audio_device *adev)
+{
+ ALOGD("%s: enter", __func__);
+
+ if (us) {
+ ALOGI("%s: ultrasound has been initialized!", __func__);
+ return 0;
+ }
+
+ us = calloc(1, sizeof(struct ultrasound_device));
+ if (!us) {
+ ALOGE("%s: Out of memory!", __func__);
+ return -ENOMEM;
+ }
+
+ us->adev = adev;
+
+ us_cal_load();
+
+ ALOGD("%s: exit, status(0)", __func__);
+
+ return 0;
+}
+
+void us_deinit(void)
+{
+ ALOGD("%s: enter", __func__);
+
+ if (us) {
+ free(us);
+ us = NULL;
+ }
+
+ ALOGD("%s: exit", __func__);
+}
+
+int stop_us(void)
+{
+ struct audio_usecase *rx_usecase, *tx_usecase;
+ int rc = 0;
+
+ ALOGD("%s: enter usecase: ultrasound", __func__);
+
+ us->state = ULTRASOUND_STATUS_STOPPED;
+ if (us->rx_pcm) {
+ pcm_close(us->rx_pcm);
+ us->rx_pcm = NULL;
+ }
+
+ if (us->tx_pcm) {
+ pcm_close(us->tx_pcm);
+ us->tx_pcm = NULL;
+ }
+
+ rx_usecase = get_usecase_from_list(us->adev, USECASE_AUDIO_ULTRASOUND_RX);
+ if (!rx_usecase) {
+ ALOGE("%s: Could not find the usecase (%d) in the list",
+ __func__, USECASE_AUDIO_ULTRASOUND_RX);
+ rc = -EINVAL;
+ } else {
+ disable_audio_route(us->adev, rx_usecase);
+ disable_snd_device(us->adev, rx_usecase->out_snd_device);
+ list_remove(&rx_usecase->list);
+ free(rx_usecase);
+ }
+
+ tx_usecase = get_usecase_from_list(us->adev, USECASE_AUDIO_ULTRASOUND_TX);
+ if (!rx_usecase) {
+ ALOGE("%s: Could not find the usecase (%d) in the list",
+ __func__, USECASE_AUDIO_ULTRASOUND_TX);
+ rc = -EINVAL;
+ } else {
+ disable_audio_route(us->adev, tx_usecase);
+ disable_snd_device(us->adev, tx_usecase->in_snd_device);
+ list_remove(&tx_usecase->list);
+ free(tx_usecase);
+ }
+
+ ALOGD("%s: exit: status(%d)", __func__, rc);
+
+ return rc;
+}
+
+int us_start(void)
+{
+ int rx_device_id, tx_device_id;
+ struct audio_usecase *rx_usecase, *tx_usecase;
+
+ ALOGD("%s: enter", __func__);
+
+ if (!us || us->state == ULTRASOUND_STATUS_STARTED)
+ return -EPERM;
+
+ ALOGD("%s: enter usecase: ultrasound", __func__);
+ rx_device_id = platform_get_pcm_device_id(USECASE_AUDIO_ULTRASOUND_RX, PCM_PLAYBACK);
+ tx_device_id = platform_get_pcm_device_id(USECASE_AUDIO_ULTRASOUND_TX, PCM_CAPTURE);
+ if (rx_device_id < 0 || tx_device_id < 0) {
+ ALOGE("%s: Invalid PCM devices (rx: %d tx: %d) for the usecase(ultrasound)",
+ __func__, rx_device_id, tx_device_id);
+ stop_us();
+ ALOGE("%s: exit: status(%d)", __func__, -EIO);
+ return -EIO;
+ }
+
+ rx_usecase = calloc(1, sizeof(struct audio_usecase));
+ if (!rx_usecase) {
+ ALOGE("%s: Out of memory!", __func__);
+ return -ENOMEM;
+ }
+
+ rx_usecase->type = PCM_PLAYBACK;
+ rx_usecase->out_snd_device = SND_DEVICE_OUT_ULTRASOUND_HANDSET;
+ rx_usecase->id = USECASE_AUDIO_ULTRASOUND_RX;
+ list_add_tail(&us->adev->usecase_list, &rx_usecase->list);
+
+ enable_snd_device(us->adev, SND_DEVICE_OUT_ULTRASOUND_HANDSET);
+ enable_audio_route(us->adev, rx_usecase);
+ ALOGV("%s: Opening PCM playback device card_id(%d) device_id(%d)",
+ __func__, us->adev->snd_card, rx_device_id);
+ us->rx_pcm = pcm_open(us->adev->snd_card, rx_device_id, PCM_OUT, &pcm_config_us);
+ if (us->rx_pcm && !pcm_is_ready(us->rx_pcm)) {
+ ALOGE("%s: %s", __func__, pcm_get_error(us->rx_pcm));
+ stop_us();
+ ALOGE("%s: exit: status(%d)", __func__, -EIO);
+ return -EIO;
+ }
+
+ tx_usecase = calloc(1, sizeof(struct audio_usecase));
+ if (!tx_usecase) {
+ ALOGE("%s: Out of memory!", __func__);
+ return -ENOMEM;
+ }
+
+ tx_usecase->type = PCM_CAPTURE;
+ tx_usecase->in_snd_device = SND_DEVICE_IN_ULTRASOUND_MIC;
+ tx_usecase->id = USECASE_AUDIO_ULTRASOUND_TX;
+ list_add_tail(&us->adev->usecase_list, &tx_usecase->list);
+
+ enable_snd_device(us->adev, SND_DEVICE_IN_ULTRASOUND_MIC);
+ enable_audio_route(us->adev, tx_usecase);
+ ALOGV("%s: Opening PCM capture device card_id(%d) device_id(%d)",
+ __func__, us->adev->snd_card, tx_device_id);
+ us->tx_pcm = pcm_open(us->adev->snd_card, tx_device_id, PCM_IN, &pcm_config_us);
+ if (us->tx_pcm && !pcm_is_ready(us->tx_pcm)) {
+ ALOGD("%s: %s", __func__, pcm_get_error(us->tx_pcm));
+ stop_us();
+ ALOGE("%s: exit: status(%d)", __func__, -EIO);
+ return -EIO;
+ }
+
+ pcm_start(us->rx_pcm);
+ pcm_start(us->tx_pcm);
+ us->state = ULTRASOUND_STATUS_STARTED;
+
+ ALOGD("%s: exit, status(0)", __func__);
+
+ return 0;
+}
+
+int us_stop(void)
+{
+ ALOGD("%s: enter", __func__);
+
+ if (!us || us->state != ULTRASOUND_STATUS_STARTED)
+ return -EPERM;
+
+ stop_us();
+
+ return 0;
+}