hal: add support for compressed recording
Add support for recording through commpressed driver.
Add qahw interface layer for non standard API implementation.
Change-Id: Id1689f2ccab9bb8b920098e9cda1083b7d3ec4da
diff --git a/hal/Android.mk b/hal/Android.mk
index f971b85..570e556 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -254,6 +254,16 @@
LOCAL_SRC_FILES += audio_extn/qaf.c
endif
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_COMPRESS_INPUT)),true)
+ LOCAL_CFLAGS += -DCOMPRESS_INPUT_ENABLED
+ LOCAL_SRC_FILES += audio_extn/compress_in.c
+endif
+
+ifeq ($(strip $(BOARD_SUPPORTS_QAHW)),true)
+ LOCAL_CFLAGS += -DAUDIO_HW_EXTN_API_ENABLED
+ LOCAL_SRC_FILES += audio_hw_extn_api.c
+endif
+
LOCAL_SHARED_LIBRARIES := \
liblog \
libcutils \
@@ -262,7 +272,6 @@
libaudioroute \
libdl \
libaudioutils \
- libhardware \
libexpat
LOCAL_C_INCLUDES += \
diff --git a/hal/Makefile.am b/hal/Makefile.am
index c6e3072..6e1b9f4 100644
--- a/hal/Makefile.am
+++ b/hal/Makefile.am
@@ -123,6 +123,16 @@
AM_CFLAGS += -DCOMPRESS_METADATA_NEEDED
endif
+if COMPRESS_INPUT
+AM_CFLAGS += -DCOMPRESS_INPUT_ENABLED
+c_sources += audio_extn/compress_in.c
+endif
+
+if AUDIO_HW_EXTN_API
+AM_CFLAGS += -DAUDIO_HW_EXTN_API_ENABLED
+c_sources += audio_hw_extn_api.c
+endif
+
h_sources = audio_extn/audio_defs.h \
audio_extn/audio_extn.h \
audio_hw.h \
diff --git a/hal/audio_extn/audio_defs.h b/hal/audio_extn/audio_defs.h
index 0a7586c..cfd29e0 100644
--- a/hal/audio_extn/audio_defs.h
+++ b/hal/audio_extn/audio_defs.h
@@ -106,4 +106,9 @@
/* Set or Query stream profile type */
#define AUDIO_PARAMETER_STREAM_PROFILE "audio_stream_profile"
+/* audio inout flag for timestamp mode.
+ * check other input flags defined in audio.h for conflicts
+ */
+#define AUDIO_INPUT_FLAG_TIMESTAMP 0x80000000
+
#endif /* AUDIO_DEFS_H */
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index d7f127a..337acd1 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -593,6 +593,8 @@
uint32_t hal_format_to_pcm(audio_format_t hal_format);
void audio_extn_utils_update_direct_pcm_fragment_size(struct stream_out *out);
+size_t audio_extn_utils_convert_format_24_8_to_8_24(void *buf, size_t bytes);
+int get_snd_codec_id(audio_format_t format);
#ifndef KPI_OPTIMIZE_ENABLED
#define audio_extn_perf_lock_init() (0)
@@ -699,4 +701,25 @@
int audio_extn_snd_mon_unregister_listener(void *stream);
#endif
+#ifdef COMPRESS_INPUT_ENABLED
+bool audio_extn_cin_applicable_stream(struct stream_in *in);
+bool audio_extn_cin_attached_usecase(audio_usecase_t uc_id);
+size_t audio_extn_cin_get_buffer_size(struct stream_in *in);
+int audio_extn_cin_start_input_stream(struct stream_in *in);
+void audio_extn_cin_stop_input_stream(struct stream_in *in);
+void audio_extn_cin_close_input_stream(struct stream_in *in);
+int audio_extn_cin_read(struct stream_in *in, void *buffer,
+ size_t bytes, size_t *bytes_read);
+int audio_extn_cin_configure_input_stream(struct stream_in *in);
+#else
+#define audio_extn_cin_applicable_stream(in) (false)
+#define audio_extn_cin_attached_usecase(uc_id) (false)
+#define audio_extn_cin_get_buffer_size(in) (0)
+#define audio_extn_cin_start_input_stream(in) (0)
+#define audio_extn_cin_stop_input_stream(in) (0)
+#define audio_extn_cin_close_input_stream(in) (0)
+#define audio_extn_cin_read(in, buffer, bytes, bytes_read) (0)
+#define audio_extn_cin_configure_input_stream(in) (0)
+#endif
+
#endif /* AUDIO_EXTN_H */
diff --git a/hal/audio_extn/compress_in.c b/hal/audio_extn/compress_in.c
new file mode 100644
index 0000000..c032480
--- /dev/null
+++ b/hal/audio_extn/compress_in.c
@@ -0,0 +1,312 @@
+/*
+* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#define LOG_TAG "audio_hw_cin"
+/*#define LOG_NDEBUG 0*/
+#define LOG_NDDEBUG 0
+
+#ifdef COMPRESS_INPUT_ENABLED
+#include <cutils/log.h>
+#include <cutils/properties.h>
+#include <cutils/str_parms.h>
+#include <cutils/log.h>
+
+#include "audio_hw.h"
+#include "platform.h"
+#include "platform_api.h"
+
+#include <hardware/audio.h>
+#include <errno.h>
+#include <time.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+
+#include "audio_extn.h"
+#include "audio_defs.h"
+#include "sound/compress_params.h"
+
+/* default timestamp metadata definition if not defined in kernel*/
+#ifndef COMPRESSED_TIMESTAMP_FLAG
+#define COMPRESSED_TIMESTAMP_FLAG 0
+struct snd_codec_metadata {
+uint64_t timestamp;
+};
+#define compress_config_set_timstamp_flag(config) (-ENOSYS)
+#else
+#define compress_config_set_timstamp_flag(config) \
+ (config)->codec->flags |= COMPRESSED_TIMESTAMP_FLAG
+#endif
+
+#define COMPRESS_RECORD_NUM_FRAGMENTS 8
+
+struct cin_private_data {
+ struct compr_config compr_config;
+ struct compress *compr;
+};
+
+typedef struct cin_private_data cin_private_data_t;
+
+static unsigned int cin_usecases_state;
+
+static const audio_usecase_t cin_usecases[] = {
+ USECASE_AUDIO_RECORD_COMPRESS2,
+ USECASE_AUDIO_RECORD_COMPRESS3,
+ USECASE_AUDIO_RECORD_COMPRESS4
+};
+
+static pthread_mutex_t cin_lock = PTHREAD_MUTEX_INITIALIZER;
+
+bool audio_extn_cin_applicable_stream(struct stream_in *in)
+{
+ if (in->flags & AUDIO_INPUT_FLAG_TIMESTAMP)
+ return true;
+
+ return false;
+}
+
+/* all audio_extn_cin_xxx calls must be made on an input
+ * only after validating that input against audio_extn_cin_attached_usecase
+ * except below calls
+ * 1. audio_extn_cin_applicable_stream(in)
+ * 2. audio_extn_cin_configure_input_stream(in)
+ */
+
+bool audio_extn_cin_attached_usecase(audio_usecase_t uc_id)
+{
+ unsigned int i;
+
+ for (i = 0; i < sizeof(cin_usecases)/
+ sizeof(cin_usecases[0]); i++) {
+ if (uc_id == cin_usecases[i] &&
+ (cin_usecases_state & (0x1 << i)))
+ return true;
+ }
+ return false;
+}
+
+static audio_usecase_t get_cin_usecase(void)
+{
+ audio_usecase_t ret_uc = USECASE_INVALID;
+ unsigned int i, num_usecase = sizeof(cin_usecases) / sizeof(cin_usecases[0]);
+ char value[PROPERTY_VALUE_MAX] = {0};
+
+ property_get("audio.record.multiple.enabled", value, NULL);
+ if (!(atoi(value) || !strncmp("true", value, 4)))
+ num_usecase = 1; /* If prop is not set, limit the num of record usecases to 1 */
+
+ ALOGV("%s: num_usecase: %d", __func__, num_usecase);
+ pthread_mutex_lock(&cin_lock);
+ for (i = 0; i < num_usecase; i++) {
+ if (!(cin_usecases_state & (0x1 << i))) {
+ cin_usecases_state |= 0x1 << i;
+ ret_uc = cin_usecases[i];
+ break;
+ }
+ }
+ pthread_mutex_unlock(&cin_lock);
+ ALOGV("%s: picked usecase: %d", __func__, ret_uc);
+ return ret_uc;
+}
+
+static void free_cin_usecase(audio_usecase_t uc_id)
+{
+ unsigned int i;
+
+ ALOGV("%s: free usecase %d", __func__, uc_id);
+ pthread_mutex_lock(&cin_lock);
+ for (i = 0; i < sizeof(cin_usecases) /
+ sizeof(cin_usecases[0]); i++) {
+ if (uc_id == cin_usecases[i])
+ cin_usecases_state &= ~(0x1 << i);
+ break;
+ }
+ pthread_mutex_unlock(&cin_lock);
+}
+
+size_t audio_extn_cin_get_buffer_size(struct stream_in *in)
+{
+ size_t sz = 0;
+ cin_private_data_t *cin_data = (cin_private_data_t *) in->cin_extn;
+
+ sz = cin_data->compr_config.fragment_size;
+ if (in->flags & AUDIO_INPUT_FLAG_TIMESTAMP)
+ sz -= sizeof(struct snd_codec_metadata);
+
+ ALOGV("%s: in %p, flags 0x%x, cin_data %p, size %zd",
+ __func__, in, in->flags, cin_data, sz);
+ return sz;
+}
+
+int audio_extn_cin_start_input_stream(struct stream_in *in)
+{
+ int ret = -EINVAL;
+ struct audio_device *adev = in->dev;
+ cin_private_data_t *cin_data = (cin_private_data_t *) in->cin_extn;
+
+ ALOGV("%s: in %p, cin_data %p", __func__, in, cin_data);
+ cin_data->compr = compress_open(adev->snd_card, in->pcm_device_id,
+ COMPRESS_OUT, &cin_data->compr_config);
+ if (cin_data->compr == NULL || !is_compress_ready(cin_data->compr)) {
+ ALOGE("%s: %s", __func__,
+ cin_data->compr ? compress_get_error(cin_data->compr) : "null");
+ if (cin_data->compr) {
+ compress_close(cin_data->compr);
+ cin_data->compr = NULL;
+ }
+ ret = -EIO;
+ } else {
+ ret = 0;
+ }
+ return ret;
+}
+
+void audio_extn_cin_stop_input_stream(struct stream_in *in)
+{
+ cin_private_data_t *cin_data = (cin_private_data_t *) in->cin_extn;
+
+ ALOGV("%s: in %p, cin_data %p", __func__, in, cin_data);
+ if (cin_data->compr) {
+ compress_close(cin_data->compr);
+ cin_data->compr = NULL;
+ }
+}
+
+void audio_extn_cin_close_input_stream(struct stream_in *in)
+{
+ cin_private_data_t *cin_data = (cin_private_data_t *) in->cin_extn;
+
+ ALOGV("%s: in %p, cin_data %p", __func__, in, cin_data);
+ if (cin_data) {
+ free(cin_data->compr_config.codec);
+ free(cin_data);
+ }
+ free_cin_usecase(in->usecase);
+}
+
+int audio_extn_cin_read(struct stream_in *in, void *buffer,
+ size_t bytes, size_t *bytes_read)
+{
+ int ret = -EINVAL;
+ size_t read_size = bytes;
+ size_t mdata_size = (sizeof(struct snd_codec_metadata));
+ cin_private_data_t *cin_data = (cin_private_data_t *) in->cin_extn;
+
+ if (cin_data->compr) {
+ /* start stream if not already done */
+ if (!is_compress_running(cin_data->compr))
+ compress_start(cin_data->compr);
+
+ if (!(in->flags & AUDIO_INPUT_FLAG_TIMESTAMP))
+ mdata_size = 0;
+
+ if (buffer && read_size) {
+ read_size = compress_read(cin_data->compr, buffer, read_size);
+ if (read_size == bytes) {
+ /* set ret to 0 if compress_read succeeded*/
+ ret = 0;
+ *bytes_read = bytes;
+ /* data from DSP comes in 24_8 format, convert it to 8_24 */
+ if (in->format == AUDIO_FORMAT_PCM_8_24_BIT) {
+ if (audio_extn_utils_convert_format_24_8_to_8_24(
+ (char *)buffer + mdata_size, bytes) != bytes)
+ ret = -EIO;
+ }
+ } else {
+ ret = errno;
+ ALOGE("%s: failed error = %d, read = %zd, err_str %s", __func__,
+ ret, read_size, compress_get_error(cin_data->compr));
+ }
+ }
+ }
+ ALOGV("%s: in %p, flags 0x%x, buf %p, bytes %zd, read_size %zd, ret %d",
+ __func__, in, in->flags, buffer, bytes, read_size, ret);
+ return ret;
+}
+
+int audio_extn_cin_configure_input_stream(struct stream_in *in)
+{
+ struct audio_device *adev = in->dev;
+ struct audio_config config = {.format = 0};
+ int ret = 0, buffer_size = 0, meta_size = sizeof(struct snd_codec_metadata);
+ cin_private_data_t *cin_data = NULL;
+
+ if (!COMPRESSED_TIMESTAMP_FLAG) {
+ ALOGE("%s: timestamp mode not supported!", __func__);
+ return -EINVAL;
+ }
+
+ cin_data = (cin_private_data_t *) calloc(1, sizeof(cin_private_data_t));
+ in->cin_extn = (void *)cin_data;
+ if (!cin_data) {
+ ALOGE("%s, allocation for private data failed!", __func__);
+ return -ENOMEM;
+ }
+
+ cin_data->compr_config.codec = (struct snd_codec *)
+ calloc(1, sizeof(struct snd_codec));
+ if (!cin_data->compr_config.codec) {
+ ALOGE("%s, allocation for codec data failed!", __func__);
+ ret = -ENOMEM;
+ goto err_config;
+ }
+
+ in->usecase = get_cin_usecase();
+ if (in->usecase == USECASE_INVALID) {
+ ALOGE("%s, Max allowed compress record usecase reached!", __func__);
+ ret = -EEXIST;
+ goto err_config;
+ }
+
+ config.sample_rate = in->sample_rate;
+ config.channel_mask = in->channel_mask;
+ config.format = in->format;
+ in->config.channels = audio_channel_count_from_in_mask(in->channel_mask);
+ buffer_size = adev->device.get_input_buffer_size(&adev->device, &config);
+
+ cin_data->compr_config.fragment_size = buffer_size;
+ cin_data->compr_config.codec->id = get_snd_codec_id(in->format);
+ cin_data->compr_config.fragments = COMPRESS_RECORD_NUM_FRAGMENTS;
+ cin_data->compr_config.codec->sample_rate = in->sample_rate;
+ cin_data->compr_config.codec->ch_in = in->config.channels;
+ cin_data->compr_config.codec->ch_out = in->config.channels;
+ cin_data->compr_config.codec->format = hal_format_to_alsa(in->format);
+ if (in->flags & AUDIO_INPUT_FLAG_TIMESTAMP) {
+ compress_config_set_timstamp_flag(&cin_data->compr_config);
+ cin_data->compr_config.fragment_size += meta_size;
+ }
+ ALOGD("%s: format %d flags 0x%x SR %d CM 0x%x buf_size %d in %p",
+ __func__, in->format, in->flags, in->sample_rate, in->channel_mask,
+ cin_data->compr_config.fragment_size, in);
+ return ret;
+
+err_config:
+ audio_extn_cin_close_input_stream(in);
+ return ret;
+}
+#endif /* COMPRESS_INPUT_ENABLED end */
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index d4ffadd..b14b1e7 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -34,6 +34,7 @@
#include "platform_api.h"
#include "audio_extn.h"
#include "voice.h"
+#include "sound/compress_params.h"
#ifdef AUDIO_EXTERNAL_HDMI_ENABLED
#ifdef HDMI_PASSTHROUGH_ENABLED
@@ -104,6 +105,7 @@
STRING_TO_ENUM(AUDIO_INPUT_FLAG_HW_HOTWORD),
STRING_TO_ENUM(AUDIO_INPUT_FLAG_RAW),
STRING_TO_ENUM(AUDIO_INPUT_FLAG_SYNC),
+ STRING_TO_ENUM(AUDIO_INPUT_FLAG_TIMESTAMP),
};
const struct string_to_enum s_format_name_to_enum_table[] = {
@@ -1081,6 +1083,66 @@
}
}
+/* converts pcm format 24_8 to 8_24 inplace */
+size_t audio_extn_utils_convert_format_24_8_to_8_24(void *buf, size_t bytes)
+{
+ size_t i = 0;
+ int *int_buf_stream = buf;
+
+ if ((bytes % 4) != 0) {
+ ALOGE("%s: wrong inout buffer! ... is not 32 bit aligned ", __func__);
+ return -EINVAL;
+ }
+
+ for (; i < (bytes / 4); i++)
+ int_buf_stream[i] >>= 8;
+
+ return bytes;
+}
+
+int get_snd_codec_id(audio_format_t format)
+{
+ int id = 0;
+
+ switch (format & AUDIO_FORMAT_MAIN_MASK) {
+ case AUDIO_FORMAT_MP3:
+ id = SND_AUDIOCODEC_MP3;
+ break;
+ case AUDIO_FORMAT_AAC:
+ id = SND_AUDIOCODEC_AAC;
+ break;
+ case AUDIO_FORMAT_AAC_ADTS:
+ id = SND_AUDIOCODEC_AAC;
+ break;
+ case AUDIO_FORMAT_PCM_OFFLOAD:
+ case AUDIO_FORMAT_PCM:
+ id = SND_AUDIOCODEC_PCM;
+ break;
+ case AUDIO_FORMAT_FLAC:
+ id = SND_AUDIOCODEC_FLAC;
+ break;
+ case AUDIO_FORMAT_ALAC:
+ id = SND_AUDIOCODEC_ALAC;
+ break;
+ case AUDIO_FORMAT_APE:
+ id = SND_AUDIOCODEC_APE;
+ break;
+ case AUDIO_FORMAT_VORBIS:
+ id = SND_AUDIOCODEC_VORBIS;
+ break;
+ case AUDIO_FORMAT_WMA:
+ id = SND_AUDIOCODEC_WMA;
+ break;
+ case AUDIO_FORMAT_WMA_PRO:
+ id = SND_AUDIOCODEC_WMA_PRO;
+ break;
+ default:
+ ALOGE("%s: Unsupported audio format :%x", __func__, format);
+ }
+
+ return id;
+}
+
void audio_extn_utils_send_audio_calibration(struct audio_device *adev,
struct audio_usecase *usecase)
{
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index ca5d3ad..d275e3d 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -227,6 +227,9 @@
[USECASE_AUDIO_RECORD] = "audio-record",
[USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
+ [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
+ [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
+ [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
[USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
[USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
[USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
@@ -505,62 +508,6 @@
(uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
}
-static int get_snd_codec_id(audio_format_t format)
-{
- int id = 0;
-
- switch (format & AUDIO_FORMAT_MAIN_MASK) {
- case AUDIO_FORMAT_MP3:
- id = SND_AUDIOCODEC_MP3;
- break;
- case AUDIO_FORMAT_AAC:
- id = SND_AUDIOCODEC_AAC;
- break;
- case AUDIO_FORMAT_AAC_ADTS:
- id = SND_AUDIOCODEC_AAC;
- break;
- case AUDIO_FORMAT_PCM:
- id = SND_AUDIOCODEC_PCM;
- break;
- case AUDIO_FORMAT_FLAC:
- id = SND_AUDIOCODEC_FLAC;
- break;
- case AUDIO_FORMAT_ALAC:
- id = SND_AUDIOCODEC_ALAC;
- break;
- case AUDIO_FORMAT_APE:
- id = SND_AUDIOCODEC_APE;
- break;
- case AUDIO_FORMAT_DSD:
- id = SND_AUDIOCODEC_DSD;
- break;
- case AUDIO_FORMAT_VORBIS:
- id = SND_AUDIOCODEC_VORBIS;
- break;
- case AUDIO_FORMAT_WMA:
- id = SND_AUDIOCODEC_WMA;
- break;
- case AUDIO_FORMAT_WMA_PRO:
- id = SND_AUDIOCODEC_WMA_PRO;
- break;
- case AUDIO_FORMAT_AC3:
- id = SND_AUDIOCODEC_AC3;
- break;
- case AUDIO_FORMAT_E_AC3:
- case AUDIO_FORMAT_E_AC3_JOC:
- id = SND_AUDIOCODEC_EAC3;
- break;
- case AUDIO_FORMAT_DTS:
- case AUDIO_FORMAT_DTS_HD:
- id = SND_AUDIOCODEC_DTS;
- break;
- default:
- ALOGE("%s: Unsupported audio format :%x", __func__, format);
- }
-
- return id;
-}
-
int get_snd_card_state(struct audio_device *adev)
{
int snd_scard_state;
@@ -1750,6 +1697,14 @@
ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
__func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
+ if (audio_extn_cin_attached_usecase(in->usecase)) {
+ ret = audio_extn_cin_start_input_stream(in);
+ if (ret)
+ goto error_open;
+ else
+ goto done_open;
+ }
+
unsigned int flags = PCM_IN;
unsigned int pcm_open_retry_count = 0;
@@ -1795,6 +1750,7 @@
goto error_open;
}
+done_open:
audio_extn_perf_lock_release(&adev->perf_lock_handle);
ALOGD("%s: exit", __func__);
@@ -3400,6 +3356,8 @@
return voice_extn_compress_voip_in_get_buffer_size(in);
else if(audio_extn_compr_cap_usecase_supported(in->usecase))
return audio_extn_compr_cap_get_buffer_size(in->config.format);
+ else if(audio_extn_cin_attached_usecase(in->usecase))
+ return audio_extn_cin_get_buffer_size(in);
return in->config.period_size * in->af_period_multiplier *
audio_stream_in_frame_size((const struct audio_stream_in *)stream);
@@ -3450,6 +3408,8 @@
voice_extn_compress_voip_close_input_stream(stream);
ALOGD("VOIP input entered standby");
} else {
+ if (audio_extn_cin_attached_usecase(in->usecase))
+ audio_extn_cin_stop_input_stream(in);
if (in->pcm) {
pcm_close(in->pcm);
in->pcm = NULL;
@@ -3586,7 +3546,7 @@
struct audio_device *adev = in->dev;
int ret = -1;
int snd_scard_state = get_snd_card_state(adev);
- int *int_buf_stream = NULL;
+ size_t bytes_read = 0;
lock_input_stream(in);
@@ -3620,14 +3580,16 @@
// what's the duration requested by the client?
long ns = 0;
- if (in->config.rate)
+ if (in->pcm && in->config.rate)
ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
in->config.rate;
request_in_focus(in, ns);
bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
- if (in->pcm) {
+ if (audio_extn_cin_attached_usecase(in->usecase)) {
+ ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
+ } else if (in->pcm) {
if (audio_extn_ssr_get_stream() == in) {
ret = audio_extn_ssr_read(stream, buffer, bytes);
} else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
@@ -3636,23 +3598,19 @@
ret = pcm_mmap_read(in->pcm, buffer, bytes);
} else {
ret = pcm_read(in->pcm, buffer, bytes);
- if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
- if (bytes % 4 == 0) {
- /* data from DSP comes in 24_8 format, convert it to 8_24 */
- int_buf_stream = buffer;
- size_t itt = 0;
- for (itt = 0; itt < bytes/4 ; itt++) {
- int_buf_stream[itt] >>= 8;
- }
- } else {
- ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
+ /* data from DSP comes in 24_8 format, convert it to 8_24 */
+ if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
+ if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
+ != bytes) {
ret = -EINVAL;
goto exit;
}
- } if (ret < 0) {
+ } else if (ret < 0) {
ret = -errno;
}
}
+ /* bytes read is always set to bytes for non compress usecases */
+ bytes_read = bytes;
}
release_in_focus(in);
@@ -3686,7 +3644,7 @@
usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
in_get_sample_rate(&in->stream.common));
}
- return bytes;
+ return bytes_read;
}
static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
@@ -4606,7 +4564,7 @@
audio_devices_t devices,
struct audio_config *config,
struct audio_stream_in **stream_in,
- audio_input_flags_t flags __unused,
+ audio_input_flags_t flags,
const char *address __unused,
audio_source_t source)
{
@@ -4660,17 +4618,6 @@
in->capture_handle = handle;
in->flags = flags;
- /* Update config params with the requested sample rate and channels */
- in->usecase = USECASE_AUDIO_RECORD;
- if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
- (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
- is_low_latency = true;
-#if LOW_LATENCY_CAPTURE_USE_CASE
- in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
-#endif
- in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
- }
-
in->format = config->format;
if (in->realtime) {
in->config = pcm_config_audio_capture_rt;
@@ -4684,6 +4631,58 @@
}
in->bit_width = 16;
+ /* restrict 24 bit capture for unprocessed source only
+ * for other sources if 24 bit requested reject 24 and set 16 bit capture only
+ */
+ if (config->format == AUDIO_FORMAT_DEFAULT) {
+ config->format = AUDIO_FORMAT_PCM_16_BIT;
+ } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
+ (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
+ (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
+ (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
+ bool ret_error = false;
+ in->bit_width = 24;
+ /* 24 bit is restricted to UNPROCESSED source only,also format supported
+ from HAL is 24_packed and 8_24
+ *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
+ 24_packed return error indicating supported format is 24_packed
+ *> In case of any other source requesting 24 bit or float return error
+ indicating format supported is 16 bit only.
+
+ on error flinger will retry with supported format passed
+ */
+ if ((source != AUDIO_SOURCE_UNPROCESSED) &&
+ (source != AUDIO_SOURCE_CAMCORDER)) {
+ config->format = AUDIO_FORMAT_PCM_16_BIT;
+ if (config->sample_rate > 48000)
+ config->sample_rate = 48000;
+ ret_error = true;
+ } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
+ in->config.format = PCM_FORMAT_S24_3LE;
+ } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
+ in->config.format = PCM_FORMAT_S24_LE;
+ } else {
+ config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
+ ret_error = true;
+ }
+
+ if (ret_error) {
+ ret = -EINVAL;
+ goto err_open;
+ }
+ }
+
+ /* Update config params with the requested sample rate and channels */
+ in->usecase = USECASE_AUDIO_RECORD;
+ if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
+ (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
+ is_low_latency = true;
+#if LOW_LATENCY_CAPTURE_USE_CASE
+ in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
+#endif
+ in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
+ }
+
if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
if (adev->mode != AUDIO_MODE_IN_CALL) {
ret = -EINVAL;
@@ -4723,48 +4722,11 @@
audio_extn_compr_cap_format_supported(config->format) &&
(in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
audio_extn_compr_cap_init(in);
+ } else if (audio_extn_cin_applicable_stream(in)) {
+ ret = audio_extn_cin_configure_input_stream(in);
+ if (ret)
+ goto err_open;
} else {
- /* restrict 24 bit capture for unprocessed source only
- * for other sources if 24 bit requested reject 24 and set 16 bit capture only
- */
- if (config->format == AUDIO_FORMAT_DEFAULT) {
- config->format = AUDIO_FORMAT_PCM_16_BIT;
- } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
- (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
- (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
- (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
- bool ret_error = false;
- in->bit_width = 24;
- /* 24 bit is restricted to UNPROCESSED source only,also format supported
- from HAL is 24_packed and 8_24
- *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
- 24_packed return error indicating supported format is 24_packed
- *> In case of any other source requesting 24 bit or float return error
- indicating format supported is 16 bit only.
-
- on error flinger will retry with supported format passed
- */
- if ((source != AUDIO_SOURCE_UNPROCESSED) &&
- (source != AUDIO_SOURCE_CAMCORDER)) {
- config->format = AUDIO_FORMAT_PCM_16_BIT;
- if( config->sample_rate > 48000)
- config->sample_rate = 48000;
- ret_error = true;
- } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
- in->config.format = PCM_FORMAT_S24_3LE;
- } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
- in->config.format = PCM_FORMAT_S24_LE;
- } else {
- config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
- ret_error = true;
- }
-
- if (ret_error) {
- ret = -EINVAL;
- goto err_open;
- }
- }
-
in->config.channels = channel_count;
if (!in->realtime) {
in->format = config->format;
@@ -4831,9 +4793,11 @@
audio_extn_ssr_deinit();
}
- if(audio_extn_compr_cap_enabled() &&
+ if (audio_extn_compr_cap_enabled() &&
audio_extn_compr_cap_format_supported(in->config.format))
audio_extn_compr_cap_deinit();
+ if (audio_extn_cin_attached_usecase(in->usecase))
+ audio_extn_cin_close_input_stream(in);
if (in->is_st_session) {
ALOGV("%s: sound trigger pcm stop lab", __func__);
@@ -4872,6 +4836,7 @@
platform_deinit(adev->platform);
if (adev->adm_deinit)
adev->adm_deinit(adev->adm_data);
+ qahwi_deinit(device);
free(device);
adev = NULL;
}
@@ -5120,6 +5085,7 @@
if (adev->adm_init)
adev->adm_data = adev->adm_init();
+ qahwi_init(*device);
audio_extn_perf_lock_init();
ALOGV("%s: exit", __func__);
return 0;
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 8402578..38ac547 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -47,6 +47,7 @@
#include <audio_route/audio_route.h>
#include "audio_defs.h"
#include "voice.h"
+#include "audio_hw_extn_api.h"
#define VISUALIZER_LIBRARY_PATH "/system/lib/soundfx/libqcomvisualizer.so"
#define OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH "/system/lib/soundfx/libqcompostprocbundle.so"
@@ -117,6 +118,9 @@
/* Capture usecases */
USECASE_AUDIO_RECORD,
USECASE_AUDIO_RECORD_COMPRESS,
+ USECASE_AUDIO_RECORD_COMPRESS2,
+ USECASE_AUDIO_RECORD_COMPRESS3,
+ USECASE_AUDIO_RECORD_COMPRESS4,
USECASE_AUDIO_RECORD_LOW_LATENCY,
USECASE_AUDIO_RECORD_FM_VIRTUAL,
@@ -273,6 +277,8 @@
bool realtime;
int af_period_multiplier;
struct stream_app_type_cfg app_type_cfg;
+ void *cin_extn;
+ qahwi_stream_in_t qahwi_in;
struct audio_device *dev;
};
@@ -413,6 +419,7 @@
int perf_lock_opts_size;
bool native_playback_enabled;
bool asrc_mode_enabled;
+ qahwi_device_t qahwi_dev;
};
int select_devices(struct audio_device *adev,
diff --git a/hal/audio_hw_extn_api.c b/hal/audio_hw_extn_api.c
new file mode 100644
index 0000000..bfeda9b
--- /dev/null
+++ b/hal/audio_hw_extn_api.c
@@ -0,0 +1,187 @@
+/*
+* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#define LOG_TAG "qahwi"
+/*#define LOG_NDEBUG 0*/
+#define LOG_NDDEBUG 0
+
+#include <errno.h>
+#include <cutils/log.h>
+
+#include <hardware/audio.h>
+#include "sound/compress_params.h"
+#include "audio_hw.h"
+#include "audio_extn.h"
+#include "audio_hw_extn_api.h"
+
+/* default timestamp metadata definition if not defined in kernel*/
+#ifndef COMPRESSED_TIMESTAMP_FLAG
+#define COMPRESSED_TIMESTAMP_FLAG 0
+struct snd_codec_metadata {
+uint64_t timestamp;
+};
+#endif
+
+ssize_t qahwi_in_read_v2(struct audio_stream_in *stream, void* buffer,
+ size_t bytes, uint64_t *timestamp)
+{
+ struct stream_in *in = (struct stream_in *)stream;
+ struct snd_codec_metadata *mdata = NULL;
+ size_t mdata_size = 0, bytes_read = 0;
+ char *buf = NULL;
+ size_t ret = 0;
+
+ if (!in->qahwi_in.is_inititalized) {
+ ALOGE("%s: invalid state!", __func__);
+ return -EINVAL;
+ }
+ if (COMPRESSED_TIMESTAMP_FLAG &&
+ (in->flags & AUDIO_INPUT_FLAG_TIMESTAMP)) {
+ if (bytes != in->stream.common.get_buffer_size(&stream->common)) {
+ ALOGE("%s: bytes requested must be fragment size in timestamp mode!", __func__);
+ return -EINVAL;
+ }
+ mdata_size = sizeof(struct snd_codec_metadata);
+ buf = (char *) in->qahwi_in.ibuf;
+ ret = in->qahwi_in.base.read(&in->stream, (void *)buf, bytes + mdata_size);
+ if (ret == bytes + mdata_size) {
+ bytes_read = bytes;
+ memcpy(buffer, buf + mdata_size, bytes);
+ if (timestamp) {
+ mdata = (struct snd_codec_metadata *) buf;
+ *timestamp = mdata->timestamp;
+ }
+ } else {
+ ALOGE("%s: error! read returned %zd", __func__, ret);
+ }
+ } else {
+ bytes_read = in->qahwi_in.base.read(stream, buffer, bytes);
+ if (timestamp)
+ *timestamp = (uint64_t ) -1;
+ }
+ ALOGV("%s: flag 0x%x, bytes %zd, read %zd, ret %zd",
+ __func__, in->flags, bytes, bytes_read, ret);
+ return bytes_read;
+}
+
+static void qahwi_close_input_stream(struct audio_hw_device *dev,
+ struct audio_stream_in *stream_in)
+{
+ struct audio_device *adev = (struct audio_device *) dev;
+ struct stream_in *in = (struct stream_in *)stream_in;
+
+ ALOGV("%s", __func__);
+ if (!adev->qahwi_dev.is_inititalized || !in->qahwi_in.is_inititalized) {
+ ALOGE("%s: invalid state!", __func__);
+ return;
+ }
+ if (in->qahwi_in.ibuf)
+ free(in->qahwi_in.ibuf);
+ adev->qahwi_dev.base.close_input_stream(dev, stream_in);
+}
+
+static int qahwi_open_input_stream(struct audio_hw_device *dev,
+ audio_io_handle_t handle,
+ audio_devices_t devices,
+ struct audio_config *config,
+ struct audio_stream_in **stream_in,
+ audio_input_flags_t flags,
+ const char *address,
+ audio_source_t source)
+{
+ struct audio_device *adev = (struct audio_device *) dev;
+ struct stream_in *in = NULL;
+ size_t buf_size = 0, mdata_size = 0;
+ int ret = 0;
+
+ ALOGV("%s: dev_init %d, flags 0x%x", __func__,
+ adev->qahwi_dev.is_inititalized, flags);
+ if (!adev->qahwi_dev.is_inititalized) {
+ ALOGE("%s: invalid state!", __func__);
+ return -EINVAL;
+ }
+
+ ret = adev->qahwi_dev.base.open_input_stream(dev, handle, devices, config,
+ stream_in, flags, address, source);
+ if (ret)
+ return ret;
+
+ in = (struct stream_in *)*stream_in;
+ // keep adev fptrs before overriding
+ in->qahwi_in.base = in->stream;
+
+ in->qahwi_in.is_inititalized = true;
+
+ if (COMPRESSED_TIMESTAMP_FLAG &&
+ (flags & AUDIO_INPUT_FLAG_TIMESTAMP)) {
+ // set read to NULL as this is not supported in timestamp mode
+ in->stream.read = NULL;
+
+ mdata_size = sizeof(struct snd_codec_metadata);
+ buf_size = mdata_size +
+ in->qahwi_in.base.common.get_buffer_size(&in->stream.common);
+
+ in->qahwi_in.ibuf = malloc(buf_size);
+ if (!in->qahwi_in.ibuf) {
+ ALOGE("%s: allocation failed for timestamp metadata!", __func__);
+ qahwi_close_input_stream(dev, &in->stream);
+ *stream_in = NULL;
+ ret = -ENOMEM;
+ }
+ ALOGD("%s: ibuf %p, buff_size %zd",
+ __func__, in->qahwi_in.ibuf, buf_size);
+ }
+ return ret;
+}
+
+void qahwi_init(hw_device_t *device)
+{
+ struct audio_device *adev = (struct audio_device *) device;
+
+ ALOGD("%s", __func__);
+
+ // keep adev fptrs before overriding,
+ // as it might be used internally by overriding implementation
+ adev->qahwi_dev.base = adev->device;
+
+ adev->device.open_input_stream = qahwi_open_input_stream;
+ adev->device.close_input_stream = qahwi_close_input_stream;
+
+ adev->qahwi_dev.is_inititalized = true;
+}
+void qahwi_deinit(hw_device_t *device)
+{
+ struct audio_device *adev = (struct audio_device *) device;
+
+ ALOGV("%s: is_initialized %d", __func__, adev->qahwi_dev.is_inititalized);
+ if (!adev->qahwi_dev.is_inititalized) {
+ ALOGE("%s: invalid state!", __func__);
+ }
+}
+
diff --git a/hal/audio_hw_extn_api.h b/hal/audio_hw_extn_api.h
new file mode 100644
index 0000000..e5fa9ec
--- /dev/null
+++ b/hal/audio_hw_extn_api.h
@@ -0,0 +1,60 @@
+/*
+* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef AUDIO_HW_EXTN_API_H
+#define AUDIO_HW_EXTN_API_H
+__BEGIN_DECLS
+#ifdef AUDIO_HW_EXTN_API_ENABLED
+#include <hardware/audio.h>
+typedef struct qahwi_stream_in qahwi_stream_in_t;
+typedef struct qahwi_device qahwi_device_t;
+
+struct qahwi_stream_in {
+ struct audio_stream_in base;
+ bool is_inititalized;
+ void *ibuf;
+};
+
+struct qahwi_device {
+ struct audio_hw_device base;
+ bool is_inititalized;
+};
+
+void qahwi_init(hw_device_t *device);
+void qahwi_deinit(hw_device_t *device);
+#else
+typedef void *qahwi_stream_in_t;
+typedef void *qahwi_device_t;
+
+#define qahwi_init(device) (0)
+#define qahwi_deinit(device) (0)
+#endif // AUDIO_HW_EXTN_API_ENABLED
+
+__END_DECLS
+#endif // AUDIO_HW_EXTN_API_H
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 012638c..a6de6e9 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -301,6 +301,9 @@
[USECASE_AUDIO_PLAYBACK_ULL] = {MULTIMEDIA3_PCM_DEVICE, MULTIMEDIA3_PCM_DEVICE},
[USECASE_AUDIO_RECORD] = {AUDIO_RECORD_PCM_DEVICE, AUDIO_RECORD_PCM_DEVICE},
[USECASE_AUDIO_RECORD_COMPRESS] = {COMPRESS_CAPTURE_DEVICE, COMPRESS_CAPTURE_DEVICE},
+ [USECASE_AUDIO_RECORD_COMPRESS2] = {-1, -1},
+ [USECASE_AUDIO_RECORD_COMPRESS3] = {-1, -1},
+ [USECASE_AUDIO_RECORD_COMPRESS4] = {-1, -1},
[USECASE_AUDIO_RECORD_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
LOWLATENCY_PCM_DEVICE},
[USECASE_AUDIO_RECORD_FM_VIRTUAL] = {MULTIMEDIA2_PCM_DEVICE,
@@ -753,6 +756,10 @@
{TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD9)},
{TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_ULL)},
{TO_NAME_INDEX(USECASE_AUDIO_RECORD)},
+ {TO_NAME_INDEX(USECASE_AUDIO_RECORD_COMPRESS)},
+ {TO_NAME_INDEX(USECASE_AUDIO_RECORD_COMPRESS2)},
+ {TO_NAME_INDEX(USECASE_AUDIO_RECORD_COMPRESS3)},
+ {TO_NAME_INDEX(USECASE_AUDIO_RECORD_COMPRESS4)},
{TO_NAME_INDEX(USECASE_AUDIO_RECORD_LOW_LATENCY)},
{TO_NAME_INDEX(USECASE_VOICE_CALL)},
{TO_NAME_INDEX(USECASE_VOICE2_CALL)},
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 3abb904..7bfc5de 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -286,6 +286,9 @@
[USECASE_AUDIO_RECORD] = {AUDIO_RECORD_PCM_DEVICE, AUDIO_RECORD_PCM_DEVICE},
[USECASE_AUDIO_RECORD_COMPRESS] = {COMPRESS_CAPTURE_DEVICE, COMPRESS_CAPTURE_DEVICE},
+ [USECASE_AUDIO_RECORD_COMPRESS2] = {-1, -1},
+ [USECASE_AUDIO_RECORD_COMPRESS3] = {-1, -1},
+ [USECASE_AUDIO_RECORD_COMPRESS4] = {-1, -1},
[USECASE_AUDIO_RECORD_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
LOWLATENCY_PCM_DEVICE},
[USECASE_AUDIO_RECORD_FM_VIRTUAL] = {MULTIMEDIA2_PCM_DEVICE,
@@ -721,6 +724,10 @@
{TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD8)},
{TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD9)},
{TO_NAME_INDEX(USECASE_AUDIO_RECORD)},
+ {TO_NAME_INDEX(USECASE_AUDIO_RECORD_COMPRESS)},
+ {TO_NAME_INDEX(USECASE_AUDIO_RECORD_COMPRESS2)},
+ {TO_NAME_INDEX(USECASE_AUDIO_RECORD_COMPRESS3)},
+ {TO_NAME_INDEX(USECASE_AUDIO_RECORD_COMPRESS4)},
{TO_NAME_INDEX(USECASE_AUDIO_RECORD_LOW_LATENCY)},
{TO_NAME_INDEX(USECASE_VOICE_CALL)},
{TO_NAME_INDEX(USECASE_VOICE2_CALL)},