Merge tag 'AU_LINUX_ANDROID_LA.BF64.1.05.00.00.021.095' into merge_branch
AU_LINUX_ANDROID_LA.BF64.1.05.00.00.021.095 based on quic/aosp/LA.BF64.1
* tag 'AU_LINUX_ANDROID_LA.BF64.1.05.00.00.021.095': (30 commits)
audio: Reject incall record request when mode is not IN_CALL
mm-audio: aenc-aac: fix integer overflow for encoded buffer timestamp calculation
hal: Add support for parsing hdmi edid information for msm8992
hal: Fix glitch in audio playback during device switch
hal: add support to query hpx state using getparameter
hal: add all compressed formats for app type selection
hal: Performance mode during recording usecase
hal: fix null pointer de-reference
hal : add 8992 for msm8992 audio
post_proc: Support Headphone:X in offload and non tunnel modes
post_proc: Add support for non-tunnel DSP audio effects
audio: Avoid mute during AFE PROXY Usecase
hal: Fix DTS HPX Get parameters
hal: bug fixes for PCM offload
hal: Fix progress bar issue during compress offload playback
hal: Fix setting stream channel map properly
hardware/qcom/audio: Integrate Eagle framework for HeadphoneX
hal: Remove setting DAP bypass /DAP on from HAL
hal: Avoid resetting device to speaker for HDMI passthrough case
hal: Audio HAL / APM changes for HDMI passthrough
...
Conflicts:
Android.mk
hal/Android.mk
hal/audio_extn/audio_extn.h
hal/audio_extn/utils.c
hal/audio_hw.c
hal/voice.c
Change-Id: Ia92b2002486894e8711a48480324479fe114aeb6
diff --git a/Android.mk b/Android.mk
index 8eee37f..cd6ee3d 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,4 +1,4 @@
-ifneq ($(filter mpq8092 msm8960 msm8226 msm8x26 msm8610 msm8974 msm8x74 apq8084 msm8916 msm8994 msm8909 thulium,$(TARGET_BOARD_PLATFORM)),)
+ifneq ($(filter mpq8092 msm8960 msm8226 msm8x26 msm8610 msm8974 msm8x74 apq8084 msm8916 msm8994 msm8909 msm8909 thulium,$(TARGET_BOARD_PLATFORM)),)
MY_LOCAL_PATH := $(call my-dir)
diff --git a/hal/Android.mk b/hal/Android.mk
index a2e41c2..c27ac4b 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -8,7 +8,7 @@
AUDIO_PLATFORM := $(TARGET_BOARD_PLATFORM)
-ifneq ($(filter msm8974 msm8226 msm8610 apq8084 msm8994 thulium,$(TARGET_BOARD_PLATFORM)),)
+ifneq ($(filter msm8974 msm8226 msm8610 apq8084 msm8994 msm8992 thulium,$(TARGET_BOARD_PLATFORM)),)
# B-family platform uses msm8974 code base
AUDIO_PLATFORM = msm8974
MULTIPLE_HW_VARIANTS_ENABLED := true
@@ -24,6 +24,9 @@
ifneq ($(filter msm8994,$(TARGET_BOARD_PLATFORM)),)
LOCAL_CFLAGS := -DPLATFORM_MSM8994
endif
+ifneq ($(filter msm8992,$(TARGET_BOARD_PLATFORM)),)
+ LOCAL_CFLAGS := -DPLATFORM_MSM8994
+endif
ifneq ($(filter thulium,$(TARGET_BOARD_PLATFORM)),)
LOCAL_CFLAGS := -DPLATFORM_THULIUM
endif
@@ -49,6 +52,10 @@
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+ifneq ($(filter msm8994 msm8992,$(TARGET_BOARD_PLATFORM)),)
+ LOCAL_SRC_FILES += edid.c
+endif
+
ifeq ($(strip $(AUDIO_FEATURE_ENABLED_PCM_OFFLOAD)),true)
LOCAL_CFLAGS += -DPCM_OFFLOAD_ENABLED
endif
@@ -65,6 +72,10 @@
LOCAL_CFLAGS += -DAFE_PROXY_ENABLED
endif
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_KPI_OPTIMIZE)),true)
+ LOCAL_CFLAGS += -DKPI_OPTIMIZE_ENABLED
+endif
+
ifeq ($(strip $(AUDIO_FEATURE_ENABLED_FM)),true)
LOCAL_CFLAGS += -DFM_ENABLED
LOCAL_SRC_FILES += audio_extn/fm.c
@@ -124,6 +135,11 @@
LOCAL_SRC_FILES += audio_extn/compress_capture.c
endif
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_DTS_EAGLE)),true)
+ LOCAL_CFLAGS += -DDTS_EAGLE
+ LOCAL_SRC_FILES += audio_extn/dts_eagle.c
+endif
+
ifeq ($(strip $(DOLBY_DDP)),true)
LOCAL_CFLAGS += -DDS1_DOLBY_DDP_ENABLED
LOCAL_SRC_FILES += audio_extn/dolby.c
@@ -153,6 +169,10 @@
LOCAL_CFLAGS += -DRECORD_PLAY_CONCURRENCY
endif
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_ACDB_LICENSE)), true)
+ LOCAL_CFLAGS += -DDOLBY_ACDB_LICENSE
+endif
+
ifeq ($(strip $(AUDIO_FEATURE_ENABLED_DS2_DOLBY_DAP)),true)
LOCAL_CFLAGS += -DDS2_DOLBY_DAP_ENABLED
ifneq ($(strip $(DOLBY_DDP)),true)
@@ -162,6 +182,10 @@
endif
endif
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_HDMI_PASSTHROUGH)),true)
+ LOCAL_CFLAGS += -DHDMI_PASSTHROUGH_ENABLED
+endif
+
LOCAL_SHARED_LIBRARIES := \
liblog \
libcutils \
diff --git a/hal/audio_extn/AudioUtil.c b/hal/audio_extn/AudioUtil.c
new file mode 100644
index 0000000..45bf55f
--- /dev/null
+++ b/hal/audio_extn/AudioUtil.c
@@ -0,0 +1,130 @@
+/*Copyright (C) 2014 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.
+* This file was modified by DTS, Inc. The portions of the
+* code modified by DTS, Inc are copyrighted and
+* licensed separately, as follows:
+*
+* (C) 2014 DTS, Inc.
+*
+* 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 "AudioUtil"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+#include <stdlib.h>
+
+#include <cutils/properties.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sound/devdep_params.h>
+#include <sound/asound.h>
+#include "AudioUtil.h"
+
+#define ROUTE_PATH "/data/data/dts/route"
+#define DEVICE_NODE "/dev/snd/hwC0D3"
+
+static int32_t mDevices = 0;
+static int32_t mCurrDevice = 0;
+
+void create_route_node(void)
+{
+ char prop[PROPERTY_VALUE_MAX] = "true";
+ int fd;
+ property_get("use.dts_eagle", prop, "0");
+ if (!strncmp("true", prop, sizeof("true")) || atoi(prop)) {
+ ALOGV("create_route_node");
+ if ((fd=open(ROUTE_PATH, O_RDONLY)) < 0) {
+ ALOGV("No File exisit");
+ } else {
+ ALOGV("A file with the same name exist. Remove it before creating it");
+ close(fd);
+ remove(ROUTE_PATH);
+ }
+ if ((fd=creat(ROUTE_PATH, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) {
+ ALOGE("opening route node failed returned");
+ return;
+ }
+ chmod(ROUTE_PATH, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH);
+ ALOGV("opening route node successful");
+ close(fd);
+ }
+}
+
+void notify_route_node(int active_device, int devices)
+{
+ char prop[PROPERTY_VALUE_MAX] = "true";
+ char buf[1024];
+ int fd;
+ if ((mCurrDevice == active_device) &&
+ (mDevices == devices)) {
+ ALOGV("nothing to update to route node");
+ return;
+ }
+ mDevices = devices;
+ mCurrDevice = active_device;
+ property_get("use.dts_eagle", prop, "0");
+ if (!strncmp("true", prop, sizeof("true")) || atoi(prop)) {
+ ALOGV("notify active device : %d all_devices : %d", active_device, devices);
+ if ((fd=open(ROUTE_PATH, O_TRUNC|O_WRONLY)) < 0) {
+ ALOGV("Write device to route node failed");
+ } else {
+ ALOGV("Write device to route node successful");
+ snprintf(buf, sizeof(buf), "device=%d;all_devices=%d", active_device, devices);
+ int n = write(fd, buf, strlen(buf));
+ ALOGV("number of bytes written: %d", n);
+ close(fd);
+ }
+ int eaglefd = open(DEVICE_NODE, O_RDWR);
+ int32_t params[2] = {active_device, 1 /*is primary device*/};
+ if (eaglefd > 0) {
+ if(ioctl(eaglefd, DTS_EAGLE_IOCTL_SET_ACTIVE_DEVICE, ¶ms) < 0) {
+ ALOGE("DTS_EAGLE (%s): error sending primary device\n", __func__);
+ }
+ ALOGD("DTS_EAGLE (%s): sent primary device\n", __func__);
+ close(eaglefd);
+ } else {
+ ALOGE("DTS_EAGLE (%s): error opening eagle\n", __func__);
+ }
+ }
+}
+
+void remove_route_node(void)
+{
+ char prop[PROPERTY_VALUE_MAX] = "true";
+ int fd;
+ property_get("use.dts_eagle", prop, "0");
+ if (!strncmp("true", prop, sizeof("true")) || atoi(prop)) {
+ ALOGV("remove_route_node");
+ if ((fd=open(ROUTE_PATH, O_RDONLY)) < 0) {
+ ALOGV("open route node failed");
+ } else {
+ ALOGV("open route node successful");
+ ALOGV("Remove the file");
+ close(fd);
+ remove(ROUTE_PATH);
+ }
+ }
+}
diff --git a/hal/audio_extn/AudioUtil.h b/hal/audio_extn/AudioUtil.h
new file mode 100644
index 0000000..02789cc
--- /dev/null
+++ b/hal/audio_extn/AudioUtil.h
@@ -0,0 +1,46 @@
+/*Copyright (C) 2014 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.
+* This file was modified by DTS, Inc. The portions of the
+* code modified by DTS, Inc are copyrighted and
+* licensed separately, as follows:
+*
+* (C) 2014 DTS, Inc.
+*
+* 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.
+*/
+
+#ifndef AUDIO_UTIL_H_
+#define AUDIO_UTIL_H_
+
+#ifndef DTS_EAGLE
+#define create_route_node() (0)
+#define notify_route_node(active_device, devices) (0)
+#define remove_route_node() (0)
+#else
+void create_route_node(void);
+void notify_route_node(int active_device, int devices);
+void remove_route_node(void);
+#endif
+
+#endif //AUDIO_UTIL_H_
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index 5ab7018..62ab6d5 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -15,6 +15,24 @@
* 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.
+ *
+ * This file was modified by DTS, Inc. The portions of the
+ * code modified by DTS, Inc are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2014 DTS, Inc.
+ *
+ * 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 "audio_hw_extn"
@@ -23,6 +41,7 @@
#include <stdlib.h>
#include <errno.h>
+#include <dlfcn.h>
#include <cutils/properties.h>
#include <cutils/log.h>
@@ -30,6 +49,7 @@
#include "audio_extn.h"
#include "platform.h"
#include "platform_api.h"
+#include "edid.h"
#define MAX_SLEEP_RETRY 100
#define WIFI_INIT_WAIT_SLEEP 50
@@ -39,6 +59,7 @@
bool aanc_enabled;
bool custom_stereo_enabled;
uint32_t proxy_channel_num;
+ bool hpx_enabled;
};
static struct audio_extn_module aextnmod = {
@@ -46,6 +67,7 @@
.aanc_enabled = 0,
.custom_stereo_enabled = 0,
.proxy_channel_num = 2,
+ .hpx_enabled = 0,
};
#define AUDIO_PARAMETER_KEY_ANC "anc_enabled"
@@ -54,6 +76,7 @@
#define AUDIO_PARAMETER_CUSTOM_STEREO "stereo_as_dual_mono"
/* Query offload playback instances count */
#define AUDIO_PARAMETER_OFFLOAD_NUM_ACTIVE "offload_num_active"
+#define AUDIO_PARAMETER_HPX "HPX"
#ifndef FM_ENABLED
#define audio_extn_fm_set_parameters(adev, parms) (0)
@@ -107,6 +130,76 @@
}
#endif /* CUSTOM_STEREO_ENABLED */
+#ifndef DTS_EAGLE
+#define audio_extn_hpx_set_parameters(adev, parms) (0)
+#define audio_extn_hpx_get_parameters(query, reply) (0)
+#define audio_extn_check_and_set_dts_hpx_state(adev) (0)
+#else
+void audio_extn_hpx_set_parameters(struct audio_device *adev,
+ struct str_parms *parms)
+{
+ int ret = 0;
+ char value[32]={0};
+ char prop[PROPERTY_VALUE_MAX] = "false";
+ bool hpx_state = false;
+ const char *mixer_ctl_name = "Set HPX OnOff";
+ struct mixer_ctl *ctl = NULL;
+ ALOGV("%s", __func__);
+
+ property_get("use.dts_eagle", prop, "0");
+ if (strncmp("true", prop, sizeof("true")))
+ return;
+
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_HPX, value,
+ sizeof(value));
+ if (ret >= 0) {
+ if (!strncmp("ON", value, sizeof("ON")))
+ hpx_state = true;
+
+ if (hpx_state == aextnmod.hpx_enabled)
+ return;
+
+ aextnmod.hpx_enabled = hpx_state;
+ /* set HPX state on stream pp */
+ if (adev->offload_effects_set_hpx_state != NULL)
+ adev->offload_effects_set_hpx_state(hpx_state);
+
+ /* set HPX state on device pp */
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (ctl)
+ mixer_ctl_set_value(ctl, 0, aextnmod.hpx_enabled);
+ }
+}
+
+static int audio_extn_hpx_get_parameters(struct str_parms *query,
+ struct str_parms *reply)
+{
+ int ret;
+ char value[32]={0};
+
+ ALOGV("%s: hpx %d", __func__, aextnmod.hpx_enabled);
+ ret = str_parms_get_str(query, AUDIO_PARAMETER_HPX, value,
+ sizeof(value));
+ if (ret >= 0) {
+ if (aextnmod.hpx_enabled)
+ str_parms_add_str(reply, AUDIO_PARAMETER_HPX, "ON");
+ else
+ str_parms_add_str(reply, AUDIO_PARAMETER_HPX, "OFF");
+ }
+ return ret;
+}
+
+void audio_extn_check_and_set_dts_hpx_state(const struct audio_device *adev)
+{
+ char prop[PROPERTY_VALUE_MAX];
+ property_get("use.dts_eagle", prop, "0");
+ if (strncmp("true", prop, sizeof("true")))
+ return;
+ if (adev->offload_effects_set_hpx_state)
+ adev->offload_effects_set_hpx_state(aextnmod.hpx_enabled);
+}
+#endif
+
#ifndef ANC_HEADSET_ENABLED
#define audio_extn_set_anc_parameters(adev, parms) (0)
#else
@@ -235,30 +328,6 @@
#define audio_extn_set_afe_proxy_parameters(adev, parms) (0)
#define audio_extn_get_afe_proxy_parameters(query, reply) (0)
#else
-/* Front left channel. */
-#define PCM_CHANNEL_FL 1
-
-/* Front right channel. */
-#define PCM_CHANNEL_FR 2
-
-/* Front center channel. */
-#define PCM_CHANNEL_FC 3
-
-/* Left surround channel.*/
-#define PCM_CHANNEL_LS 4
-
-/* Right surround channel.*/
-#define PCM_CHANNEL_RS 5
-
-/* Low frequency effect channel. */
-#define PCM_CHANNEL_LFE 6
-
-/* Left back channel; Rear left channel. */
-#define PCM_CHANNEL_LB 8
-
-/* Right back channel; Rear right channel. */
-#define PCM_CHANNEL_RB 9
-
static int32_t afe_proxy_set_channel_mapping(struct audio_device *adev,
int channel_count)
{
@@ -460,8 +529,11 @@
audio_extn_sound_trigger_set_parameters(adev, parms);
audio_extn_listen_set_parameters(adev, parms);
audio_extn_hfp_set_parameters(adev, parms);
+ audio_extn_dts_eagle_set_parameters(adev, parms);
audio_extn_ddp_set_parameters(adev, parms);
+ audio_extn_ds2_set_parameters(adev, parms);
audio_extn_customstereo_set_parameters(adev, parms);
+ audio_extn_hpx_set_parameters(adev, parms);
}
void audio_extn_get_parameters(const struct audio_device *adev,
@@ -472,6 +544,8 @@
audio_extn_get_afe_proxy_parameters(query, reply);
audio_extn_get_fluence_parameters(adev, query, reply);
get_active_offload_usecases(adev, query, reply);
+ audio_extn_dts_eagle_get_parameters(adev, query, reply);
+ audio_extn_hpx_get_parameters(query, reply);
kv_pairs = str_parms_to_str(reply);
ALOGD_IF(kv_pairs != NULL, "%s: returns %s", __func__, kv_pairs);
@@ -505,3 +579,68 @@
return 0;
}
#endif /* AUXPCM_BT_ENABLED */
+
+#ifdef KPI_OPTIMIZE_ENABLED
+typedef int (*perf_lock_acquire_t)(int, int, int*, int);
+typedef int (*perf_lock_release_t)(int);
+
+static void *qcopt_handle;
+static perf_lock_acquire_t perf_lock_acq;
+static perf_lock_release_t perf_lock_rel;
+
+static int perf_lock_handle;
+char opt_lib_path[512] = {0};
+int perf_lock_opts[1] = {0x20E};
+
+int audio_extn_perf_lock_init(void)
+{
+ int ret = 0;
+ if (qcopt_handle == NULL) {
+ if (property_get("ro.vendor.extension_library",
+ opt_lib_path, NULL) <= 0) {
+ ALOGE("%s: Failed getting perf property \n", __func__);
+ ret = -EINVAL;
+ goto err;
+ }
+ if ((qcopt_handle = dlopen(opt_lib_path, RTLD_NOW)) == NULL) {
+ ALOGE("%s: Failed to open perf handle \n", __func__);
+ ret = -EINVAL;
+ goto err;
+ } else {
+ perf_lock_acq = (perf_lock_acquire_t)dlsym(qcopt_handle,
+ "perf_lock_acq");
+ if (perf_lock_acq == NULL) {
+ ALOGE("%s: Perf lock Acquire NULL \n", __func__);
+ ret = -EINVAL;
+ goto err;
+ }
+ perf_lock_rel = (perf_lock_release_t)dlsym(qcopt_handle,
+ "perf_lock_rel");
+ if (perf_lock_rel == NULL) {
+ ALOGE("%s: Perf lock Release NULL \n", __func__);
+ ret = -EINVAL;
+ goto err;
+ }
+ ALOGE("%s: Perf lock handles Success \n", __func__);
+ }
+ }
+err:
+ return ret;
+}
+
+void audio_extn_perf_lock_acquire(void)
+{
+ if (perf_lock_acq)
+ perf_lock_handle = perf_lock_acq(perf_lock_handle, 0, perf_lock_opts, 1);
+ else
+ ALOGE("%s: Perf lock acquire error \n", __func__);
+}
+
+void audio_extn_perf_lock_release(void)
+{
+ if (perf_lock_rel && perf_lock_handle)
+ perf_lock_rel(perf_lock_handle);
+ else
+ ALOGE("%s: Perf lock release error \n", __func__);
+}
+#endif /* KPI_OPTIMIZE_ENABLED */
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 38f1384..5aa9f2e 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -15,6 +15,24 @@
* 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.
+ *
+ * This file was modified by DTS, Inc. The portions of the
+ * code modified by DTS, Inc are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2014 DTS, Inc.
+ *
+ * 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.
*/
#ifndef AUDIO_EXTN_H
@@ -251,11 +269,38 @@
void audio_extn_compr_cap_deinit();
#endif
+#ifndef DTS_EAGLE
+#define audio_extn_dts_eagle_set_parameters(adev, parms) (0)
+#define audio_extn_dts_eagle_get_parameters(adev, query, reply) (0)
+#define audio_extn_dts_eagle_fade(adev, fade_in) (0)
+#define audio_extn_dts_create_state_notifier_node(stream_out) (0)
+#define audio_extn_dts_notify_playback_state(stream_out, has_video, sample_rate, \
+ channels, is_playing) (0)
+#define audio_extn_dts_remove_state_notifier_node(stream_out) (0)
+#define audio_extn_check_and_set_dts_hpx_state(adev) (0)
+#else
+void audio_extn_dts_eagle_set_parameters(struct audio_device *adev,
+ struct str_parms *parms);
+int audio_extn_dts_eagle_get_parameters(const struct audio_device *adev,
+ struct str_parms *query, struct str_parms *reply);
+int audio_extn_dts_eagle_fade(const struct audio_device *adev, bool fade_in);
+void audio_extn_dts_create_state_notifier_node(int stream_out);
+void audio_extn_dts_notify_playback_state(int stream_out, int has_video, int sample_rate,
+ int channels, int is_playing);
+void audio_extn_dts_remove_state_notifier_node(int stream_out);
+void audio_extn_check_and_set_dts_hpx_state(const struct audio_device *adev);
+#endif
+
#if defined(DS1_DOLBY_DDP_ENABLED) || defined(DS1_DOLBY_DAP_ENABLED)
void audio_extn_dolby_set_dmid(struct audio_device *adev);
-void audio_extn_dolby_set_license(struct audio_device *adev);
#else
#define audio_extn_dolby_set_dmid(adev) (0)
+#endif
+
+
+#if defined(DS1_DOLBY_DDP_ENABLED) || defined(DS1_DOLBY_DAP_ENABLED) || defined(DS2_DOLBY_DAP_ENABLED)
+void audio_extn_dolby_set_license(struct audio_device *adev);
+#else
#define audio_extn_dolby_set_license(adev) (0)
#endif
@@ -265,7 +310,6 @@
void audio_extn_dolby_set_endpoint(struct audio_device *adev);
#endif
-
#if defined(DS1_DOLBY_DDP_ENABLED) || defined(DS2_DOLBY_DAP_ENABLED)
bool audio_extn_is_dolby_format(audio_format_t format);
int audio_extn_dolby_get_snd_codec_id(struct audio_device *adev,
@@ -283,6 +327,34 @@
void audio_extn_ddp_set_parameters(struct audio_device *adev,
struct str_parms *parms);
void audio_extn_dolby_send_ddp_endp_params(struct audio_device *adev);
+
+#endif
+
+#ifndef HDMI_PASSTHROUGH_ENABLED
+#define audio_extn_dolby_update_passt_formats(adev, out) (0)
+#define audio_extn_dolby_update_passt_stream_configuration(adev, out) (0)
+#define audio_extn_dolby_is_passt_convert_supported(adev, out) (0)
+#define audio_extn_dolby_is_passt_supported(adev, out) (0)
+#define audio_extn_dolby_is_passthrough_stream(flags) (0)
+#define audio_extn_dolby_set_hdmi_config(adev, out) (0)
+#define audio_extn_dolby_get_passt_buffer_size(info) (0)
+#define audio_extn_dolby_set_passt_volume(out, mute) (0)
+#define audio_extn_dolby_set_passt_latency(out, latency) (0)
+#else
+int audio_extn_dolby_update_passt_formats(struct audio_device *adev,
+ struct stream_out *out);
+bool audio_extn_dolby_is_passt_convert_supported(struct audio_device *adev,
+ struct stream_out *out);
+bool audio_extn_dolby_is_passt_supported(struct audio_device *adev,
+ struct stream_out *out);
+void audio_extn_dolby_update_passt_stream_configuration(struct audio_device *adev,
+ struct stream_out *out);
+bool audio_extn_dolby_is_passthrough_stream(int flags);
+int audio_extn_dolby_set_hdmi_config(struct audio_device *adev,
+ struct stream_out *out);
+int audio_extn_dolby_get_passt_buffer_size(audio_offload_info_t* info);
+int audio_extn_dolby_set_passt_volume(struct stream_out *out, int mute);
+int audio_extn_dolby_set_passt_latency(struct stream_out *out, int latency);
#endif
#ifndef HFP_ENABLED
@@ -344,21 +416,35 @@
void audio_extn_dolby_ds2_set_endpoint(struct audio_device *adev);
int audio_extn_ds2_enable(struct audio_device *adev);
int audio_extn_dolby_set_dap_bypass(struct audio_device *adev, int state);
+void audio_extn_ds2_set_parameters(struct audio_device *adev,
+ struct str_parms *parms);
+
#else
#define audio_extn_dap_hal_init(snd_card) (0)
#define audio_extn_dap_hal_deinit() (0)
#define audio_extn_dolby_ds2_set_endpoint(adev) (0)
#define audio_extn_ds2_enable(adev) (0)
#define audio_extn_dolby_set_dap_bypass(adev, state) (0)
+#define audio_extn_ds2_set_parameters(adev, parms); (0)
#endif
typedef enum {
DAP_STATE_ON = 0,
DAP_STATE_BYPASS,
-};
+} dap_state;
#ifndef AUDIO_FORMAT_E_AC3_JOC
#define AUDIO_FORMAT_E_AC3_JOC 0x19000000UL
#endif
int b64decode(char *inp, int ilen, uint8_t* outp);
int b64encode(uint8_t *inp, int ilen, char* outp);
+
+#ifndef KPI_OPTIMIZE_ENABLED
+#define audio_extn_perf_lock_init() (0)
+#define audio_extn_perf_lock_acquire() (0)
+#define audio_extn_perf_lock_release() (0)
+#else
+int audio_extn_perf_lock_init(void);
+void audio_extn_perf_lock_acquire(void);
+void audio_extn_perf_lock_release(void);
+#endif /* KPI_OPTIMIZE_ENABLED */
#endif /* AUDIO_EXTN_H */
diff --git a/hal/audio_extn/dolby.c b/hal/audio_extn/dolby.c
index 8670367..cdfa2a1 100644
--- a/hal/audio_extn/dolby.c
+++ b/hal/audio_extn/dolby.c
@@ -18,8 +18,8 @@
*/
#define LOG_TAG "audio_hw_dolby"
-/*#define LOG_NDEBUG 0*/
-#define LOG_NDDEBUG 0
+//#define LOG_NDEBUG 0
+//#define LOG_NDDEBUG 0
#include <errno.h>
#include <cutils/properties.h>
@@ -33,6 +33,7 @@
#include "platform_api.h"
#include "audio_extn.h"
#include "sound/compress_params.h"
+#include "sound/devdep_params.h"
#ifdef DS1_DOLBY_DDP_ENABLED
@@ -407,6 +408,118 @@
}
#endif /* DS1_DOLBY_DDP_ENABLED || DS2_DOLBY_DAP_ENABLED */
+#ifdef HDMI_PASSTHROUGH_ENABLED
+int audio_extn_dolby_update_passt_formats(struct audio_device *adev,
+ struct stream_out *out) {
+ int32_t i = 0, ret = -ENOSYS;
+
+ if (platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_AC3) ||
+ platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_E_AC3)) {
+ out->supported_formats[i++] = AUDIO_FORMAT_AC3;
+ out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
+ /* Reciever must support JOC and advertise, otherwise JOC is treated as DDP */
+ out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
+ ret = 0;
+ }
+ ALOGV("%s: ret = %d", __func__, ret);
+ return ret;
+}
+
+bool audio_extn_dolby_is_passt_convert_supported(struct audio_device *adev,
+ struct stream_out *out) {
+
+ bool convert = false;
+ switch (out->format) {
+ case AUDIO_FORMAT_E_AC3:
+ case AUDIO_FORMAT_E_AC3_JOC:
+ if (!platform_is_edid_supported_format(adev->platform,
+ AUDIO_FORMAT_E_AC3)) {
+ ALOGV("%s:PASSTHROUGH_CONVERT supported", __func__);
+ convert = true;
+ }
+ break;
+ default:
+ ALOGE("%s: PASSTHROUGH_CONVERT not supported for format 0x%x",
+ __func__, out->format);
+ break;
+ }
+ ALOGE("%s: convert %d", __func__, convert);
+ return convert;
+}
+
+bool audio_extn_dolby_is_passt_supported(struct audio_device *adev,
+ struct stream_out *out) {
+ bool passt = false;
+ switch (out->format) {
+ case AUDIO_FORMAT_E_AC3:
+ if (platform_is_edid_supported_format(adev->platform, out->format)) {
+ ALOGV("%s:PASSTHROUGH supported for format %x",
+ __func__, out->format);
+ passt = true;
+ }
+ break;
+ case AUDIO_FORMAT_AC3:
+ if (platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_AC3)
+ || platform_is_edid_supported_format(adev->platform,
+ AUDIO_FORMAT_E_AC3)) {
+ ALOGV("%s:PASSTHROUGH supported for format %x",
+ __func__, out->format);
+ passt = true;
+ }
+ break;
+ case AUDIO_FORMAT_E_AC3_JOC:
+ /* Check for DDP capability in edid for JOC contents.*/
+ if (platform_is_edid_supported_format(adev->platform,
+ AUDIO_FORMAT_E_AC3)) {
+ ALOGV("%s:PASSTHROUGH supported for format %x",
+ __func__, out->format);
+ passt = true;
+ }
+ default:
+ ALOGV("%s:Passthrough not supported", __func__);
+ }
+ return passt;
+}
+
+void audio_extn_dolby_update_passt_stream_configuration(
+ struct audio_device *adev, struct stream_out *out) {
+ if (audio_extn_dolby_is_passt_supported(adev, out)) {
+ ALOGV("%s:PASSTHROUGH", __func__);
+ out->compr_config.codec->compr_passthr = PASSTHROUGH;
+ } else if (audio_extn_dolby_is_passt_convert_supported(adev, out)){
+ ALOGV("%s:PASSTHROUGH CONVERT", __func__);
+ out->compr_config.codec->compr_passthr = PASSTHROUGH_CONVERT;
+ } else {
+ ALOGV("%s:NO PASSTHROUGH", __func__);
+ out->compr_config.codec->compr_passthr = LEGACY_PCM;
+ }
+}
+
+bool audio_extn_dolby_is_passthrough_stream(int flags) {
+
+ if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH)
+ return true;
+ return false;
+}
+
+int audio_extn_dolby_set_hdmi_config(struct audio_device *adev,
+ struct stream_out *out) {
+ return platform_set_hdmi_config(out);
+}
+
+int audio_extn_dolby_get_passt_buffer_size(audio_offload_info_t* info) {
+ return platform_get_compress_passthrough_buffer_size(info);
+}
+
+int audio_extn_dolby_set_passt_volume(struct stream_out *out, int mute) {
+ return platform_set_device_params(out, DEVICE_PARAM_MUTE_ID, mute);
+}
+
+int audio_extn_dolby_set_passt_latency(struct stream_out *out, int latency) {
+ return platform_set_device_params(out, DEVICE_PARAM_LATENCY_ID, latency);
+}
+#endif /* HDMI_PASSTHROUGH_ENABLED */
+
#ifdef DS1_DOLBY_DAP_ENABLED
void audio_extn_dolby_set_endpoint(struct audio_device *adev)
{
@@ -479,6 +592,7 @@
return;
}
+#ifndef DS2_DOLBY_DAP_ENABLED
void audio_extn_dolby_set_license(struct audio_device *adev)
{
int ret, key=0;
@@ -494,8 +608,9 @@
}
property_get("audio.ds1.metainfo.key",value,"0");
+#ifdef DOLBY_ACDB_LICENSE
key = atoi(value);
-
+#endif
ALOGV("%s Setting DS1 License, key:0x%x",__func__, key);
ret = mixer_ctl_set_value(ctl, 0, key);
if (ret)
@@ -503,6 +618,7 @@
return;
}
+#endif
#endif /* DS1_DOLBY_DDP_ENABLED || DS1_DOLBY_DAP_ENABLED */
#ifdef DS2_DOLBY_DAP_ENABLED
@@ -538,11 +654,6 @@
ds2extnmod.dap_hal_set_hw_info(SND_CARD, (void*)(&snd_card));
ALOGV("%s Sound card number is:%d",__func__,snd_card);
- property_get("dmid",c_dmid,"0");
- i_dmid = atoi(c_dmid);
- ds2extnmod.dap_hal_set_hw_info(DMID, (void*)(&i_dmid));
- ALOGV("%s Dolby device manufacturer id is:%d",__func__,i_dmid);
-
platform_get_device_to_be_id_map(&device_be_id_map.device_id_to_be_id, &device_be_id_map.len);
ds2extnmod.dap_hal_set_hw_info(DEVICE_BE_ID_MAP, (void*)(&device_be_id_map));
ALOGV("%s Set be id map len:%d",__func__,device_be_id_map.len);
@@ -635,4 +746,50 @@
}
return 0;
}
+
+void audio_extn_dolby_set_license(struct audio_device *adev)
+{
+ int i_key;
+ char c_key[128] = {0};
+ char c_dmid[128] = {0};
+ int i_dmid, ret = -EINVAL;
+ struct dolby_param_license dolby_license;
+
+#ifdef DOLBY_ACDB_LICENSE
+ property_get("audio.ds1.metainfo.key",c_key,"0");
+ i_key = atoi(c_key);
+#else
+ /* As ACDB based license mechanism is disabled, force set the license key to 0*/
+ i_key = 0;
+#endif
+ property_get("dmid",c_dmid,"0");
+ i_dmid = atoi(c_dmid);
+ ALOGV("%s Setting DS1 License, key:0x%x dmid %d",__func__, i_key,i_dmid);
+ dolby_license.dmid = i_dmid;
+ dolby_license.license_key = i_key;
+ if (ds2extnmod.dap_hal_set_hw_info) {
+ ds2extnmod.dap_hal_set_hw_info(DMID, (void*)(&dolby_license.dmid));
+ } else {
+ ALOGV("%s: dap_hal_set_hw_info is NULL", __func__);
+ return ret;
+ }
+ return 0;
+}
+
+
+void audio_extn_ds2_set_parameters(struct audio_device *adev,
+ struct str_parms *parms)
+{
+ int val, ret;
+ char value[32]={0};
+
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SND_CARD_STATUS, value,
+ sizeof(value));
+ if (ret >= 0) {
+ char *snd_card_status = value + 2;
+ if (strncmp(snd_card_status, "ONLINE", sizeof("ONLINE")) == 0){
+ audio_extn_dolby_set_license(adev);
+ }
+ }
+}
#endif
diff --git a/hal/audio_extn/dts_eagle.c b/hal/audio_extn/dts_eagle.c
new file mode 100644
index 0000000..b4bbb9f
--- /dev/null
+++ b/hal/audio_extn/dts_eagle.c
@@ -0,0 +1,486 @@
+/*
+ * (C) 2014 DTS, Inc.
+ *
+ * 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 "audio_hw_dts_eagle"
+/*#define LOG_NDEBUG 0*/
+
+#include <errno.h>
+#include <math.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <cutils/log.h>
+#include <cutils/properties.h>
+#include <cutils/str_parms.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sound/asound.h>
+#include <sound/audio_effects.h>
+#include <sound/devdep_params.h>
+#include "audio_hw.h"
+#include "platform.h"
+#include "platform_api.h"
+
+#ifdef DTS_EAGLE
+
+#define AUDIO_PARAMETER_KEY_DTS_EAGLE "DTS_EAGLE"
+#define STATE_NOTIFY_FILE "/data/data/dts/stream"
+#define FADE_NOTIFY_FILE "/data/data/dts/fade"
+#define DTS_EAGLE_KEY "DTS_EAGLE"
+#define DEVICE_NODE "/dev/snd/hwC0D3"
+#define MAX_LENGTH_OF_INTEGER_IN_STRING 13
+#define PARAM_GET_MAX_SIZE 512
+
+struct dts_eagle_param_desc_alsa {
+ int alsa_effect_ID;
+ struct dts_eagle_param_desc d;
+};
+
+static struct dts_eagle_param_desc_alsa *fade_in_data = NULL;
+static struct dts_eagle_param_desc_alsa *fade_out_data = NULL;
+static int32_t mDevices = 0;
+static int32_t mCurrDevice = 0;
+static const char* DTS_EAGLE_STR = DTS_EAGLE_KEY;
+
+static int do_DTS_Eagle_params_stream(struct stream_out *out, struct dts_eagle_param_desc_alsa *t, bool get) {
+ char mixer_string[128];
+ char mixer_str_query[128];
+ struct mixer_ctl *ctl;
+ struct mixer_ctl *query_ctl;
+ int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
+
+ ALOGV("DTS_EAGLE_HAL (%s): enter", __func__);
+ snprintf(mixer_string, sizeof(mixer_string), "%s %d", "Audio Effects Config", pcm_device_id);
+ ctl = mixer_get_ctl_by_name(out->dev->mixer, mixer_string);
+ if (!ctl) {
+ ALOGE("DTS_EAGLE_HAL (%s): failed to open mixer %s", __func__, mixer_string);
+ } else if (t) {
+ int size = t->d.size + sizeof(struct dts_eagle_param_desc_alsa);
+ ALOGD("DTS_EAGLE_HAL (%s): opened mixer %s", __func__, mixer_string);
+ if (get) {
+ ALOGD("DTS_EAGLE_HAL (%s): get request", __func__);
+ snprintf(mixer_str_query, sizeof(mixer_str_query), "%s %d", "Query Audio Effect Param", pcm_device_id);
+ query_ctl = mixer_get_ctl_by_name(out->dev->mixer, mixer_str_query);
+ if (!query_ctl) {
+ ALOGE("DTS_EAGLE_HAL (%s): failed to open mixer %s", __func__, mixer_str_query);
+ return -EINVAL;
+ }
+ mixer_ctl_set_array(query_ctl, t, size);
+ return mixer_ctl_get_array(ctl, t, size);
+ }
+ ALOGD("DTS_EAGLE_HAL (%s): set request", __func__);
+ return mixer_ctl_set_array(ctl, t, size);
+ } else {
+ ALOGD("DTS_EAGLE_HAL (%s): parameter data NULL", __func__);
+ }
+ return -EINVAL;
+}
+
+static int do_DTS_Eagle_params(const struct audio_device *adev, struct dts_eagle_param_desc_alsa *t, bool get) {
+ struct listnode *node;
+ struct audio_usecase *usecase;
+ int ret = 0, sent = 0;
+
+ ALOGV("DTS_EAGLE_HAL (%s): enter", __func__);
+
+ list_for_each(node, &adev->usecase_list) {
+ usecase = node_to_item(node, struct audio_usecase, list);
+ /* set/get eagle params for offload usecases only */
+ if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
+ int tret = do_DTS_Eagle_params_stream(usecase->stream.out, t, get);
+ if (tret < 0)
+ ret = tret;
+ else
+ sent = 1;
+ }
+ }
+
+ if (!sent) {
+ int fd = open(DEVICE_NODE, O_RDWR);
+
+ if (get) {
+ ALOGD("DTS_EAGLE_HAL (%s): no stream opened, attempting to retrieve directly from cache", __func__);
+ t->d.device &= ~DTS_EAGLE_FLAG_ALSA_GET;
+ } else {
+ ALOGD("DTS_EAGLE_HAL (%s): no stream opened, attempting to send directly to cache", __func__);
+ t->d.device |= DTS_EAGLE_FLAG_IOCTL_JUSTSETCACHE;
+ }
+
+ if (fd > 0) {
+ int cmd = get ? DTS_EAGLE_IOCTL_GET_PARAM : DTS_EAGLE_IOCTL_SET_PARAM;
+ if (ioctl(fd, cmd, &t->d) < 0) {
+ ALOGE("DTS_EAGLE_HAL (%s): error sending/getting param\n", __func__);
+ ret = -EINVAL;
+ } else {
+ ALOGD("DTS_EAGLE_HAL (%s): sent/retrieved param\n", __func__);
+ }
+ close(fd);
+ } else {
+ ALOGE("DTS_EAGLE_HAL (%s): couldn't open device %s\n", __func__, DEVICE_NODE);
+ ret = -EINVAL;
+ }
+ }
+ return ret;
+}
+
+static void fade_node(bool need_data) {
+ int fd = creat(FADE_NOTIFY_FILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH), n = 0;
+ char *str = need_data ? "need" : "have";
+ if (fd < 0) {
+ ALOGE("DTS_EAGLE_HAL (%s): opening fade notifier node failed", __func__);
+ return;
+ }
+ chmod(FADE_NOTIFY_FILE, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH);
+ n = write(fd, str, strlen(str));
+ close(fd);
+ if (n > 0)
+ ALOGI("DTS_EAGLE_HAL (%s): fade notifier node set to \"%s\", %i bytes written", __func__, str, n);
+ else
+ ALOGE("DTS_EAGLE_HAL (%s): error writing to fade notifier node", __func__);
+}
+
+int audio_extn_dts_eagle_fade(const struct audio_device *adev, bool fade_in) {
+ char prop[PROPERTY_VALUE_MAX];
+
+ ALOGV("DTS_EAGLE_HAL (%s): enter with fade %s requested", __func__, fade_in ? "in" : "out");
+
+ property_get("use.dts_eagle", prop, "0");
+ if (strncmp("true", prop, sizeof("true")))
+ return 0;
+
+ if (!fade_in_data || !fade_out_data)
+ fade_node(true);
+
+ if (fade_in) {
+ if (fade_in_data)
+ return do_DTS_Eagle_params(adev, fade_in_data, false);
+ } else {
+ if (fade_out_data)
+ return do_DTS_Eagle_params(adev, fade_out_data, false);
+ }
+ return 0;
+}
+
+void audio_extn_dts_eagle_set_parameters(struct audio_device *adev, struct str_parms *parms) {
+ int ret, val;
+ char value[32] = { 0 }, prop[PROPERTY_VALUE_MAX];
+
+ ALOGV("DTS_EAGLE_HAL (%s): enter", __func__);
+
+ property_get("use.dts_eagle", prop, "0");
+ if (strncmp("true", prop, sizeof("true")))
+ return;
+
+ memset(value, 0, sizeof(value));
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_DTS_EAGLE, value, sizeof(value));
+ if (ret >= 0) {
+ int *data = NULL, id, size, offset, count, dev, dts_found = 0, fade_in = 0;
+ struct dts_eagle_param_desc_alsa *t2 = NULL, **t = &t2;
+
+ ret = str_parms_get_str(parms, "fade", value, sizeof(value));
+ if (ret >= 0) {
+ fade_in = atoi(value);
+ if (fade_in > 0) {
+ t = (fade_in == 1) ? &fade_in_data : &fade_out_data;
+ }
+ }
+
+ ret = str_parms_get_str(parms, "count", value, sizeof(value));
+ if (ret >= 0) {
+ count = atoi(value);
+ if (count > 1) {
+ int tmp_size = count * 32;
+ char *tmp = malloc(tmp_size+1);
+ data = malloc(sizeof(int) * count);
+ ALOGV("DTS_EAGLE_HAL (%s): multi count param detected, count: %d", __func__, count);
+ if (data && tmp) {
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_DTS_EAGLE, tmp, tmp_size);
+ if (ret >= 0) {
+ int idx = 0, tidx, tcnt = 0;
+ dts_found = 1;
+ do {
+ sscanf(&tmp[idx], "%i", &data[tcnt]);
+ tidx = strcspn(&tmp[idx], ",");
+ if (idx + tidx >= ret && tcnt < count-1) {
+ ALOGE("DTS_EAGLE_HAL (%s): malformed multi value string.", __func__);
+ dts_found = 0;
+ break;
+ }
+ ALOGD("DTS_EAGLE_HAL (%s): %i:%i (next %s)", __func__, tcnt, data[tcnt], &tmp[idx+tidx]);
+ idx += tidx + 1;
+ tidx = 0;
+ tcnt++;
+ } while (tcnt < count);
+ }
+ } else {
+ ALOGE("DTS_EAGLE_HAL (%s): mem alloc for multi count param parse failed.", __func__);
+ }
+ free(tmp);
+ }
+ }
+
+ if (!dts_found) {
+ data = malloc(sizeof(int));
+ if (data) {
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_DTS_EAGLE, value, sizeof(value));
+ if (ret >= 0) {
+ *data = atoi(value);
+ dts_found = 1;
+ count = 1;
+ } else {
+ ALOGE("DTS_EAGLE_HAL (%s): malformed value string.", __func__);
+ }
+ } else {
+ ALOGE("DTS_EAGLE_HAL (%s): mem alloc for param parse failed.", __func__);
+ }
+ }
+
+ if (dts_found) {
+ dts_found = 0;
+ ret = str_parms_get_str(parms, "id", value, sizeof(value));
+ if (ret >= 0) {
+ if (sscanf(value, "%x", &id) == 1) {
+ ret = str_parms_get_str(parms, "size", value, sizeof(value));
+ if (ret >= 0) {
+ size = atoi(value);
+ ret = str_parms_get_str(parms, "offset", value, sizeof(value));
+ if (ret >= 0) {
+ offset = atoi(value);
+ ret = str_parms_get_str(parms, "device", value, sizeof(value));
+ if (ret >= 0) {
+ dev = atoi(value);
+ dts_found = 1;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (dts_found && count > 1 && size != (int)(count * sizeof(int))) {
+ ALOGE("DTS_EAGLE_HAL (%s): size/count mismatch (size = %i bytes, count = %i integers / %u bytes).", __func__, size, count, count*sizeof(int));
+ } else if (dts_found) {
+ ALOGI("DTS_EAGLE_HAL (%s): param detected: %s", __func__, str_parms_to_str(parms));
+ if (!(*t))
+ *t = (struct dts_eagle_param_desc_alsa*)malloc(sizeof(struct dts_eagle_param_desc_alsa) + size);
+ if (*t) {
+ (*t)->alsa_effect_ID = DTS_EAGLE_MODULE;
+ (*t)->d.id = id;
+ (*t)->d.size = size;
+ (*t)->d.offset = offset;
+ (*t)->d.device = dev;
+ memcpy((void*)((char*)*t + sizeof(struct dts_eagle_param_desc_alsa)), data, size);
+ ALOGD("DTS_EAGLE_HAL (%s): id: 0x%X, size: %d, offset: %d, device: %d", __func__,
+ (*t)->d.id, (*t)->d.size, (*t)->d.offset, (*t)->d.device);
+ if (!fade_in) {
+ ret = do_DTS_Eagle_params(adev, *t, false);
+ if (ret < 0)
+ ALOGE("DTS_EAGLE_HAL (%s): failed setting params in kernel with error %i", __func__, ret);
+ }
+ free(t2);
+ } else {
+ ALOGE("DTS_EAGLE_HAL (%s): mem alloc for dsp structure failed.", __func__);
+ }
+ } else {
+ ALOGE("DTS_EAGLE_HAL (%s): param detected but failed parse: %s", __func__, str_parms_to_str(parms));
+ }
+ free(data);
+
+ if (fade_in > 0 && fade_in_data && fade_out_data)
+ fade_node(false);
+ }
+
+ ALOGV("DTS_EAGLE_HAL (%s): exit", __func__);
+}
+
+int audio_extn_dts_eagle_get_parameters(const struct audio_device *adev,
+ struct str_parms *query, struct str_parms *reply) {
+ int ret, val;
+ char value[32] = { 0 }, prop[PROPERTY_VALUE_MAX];
+ char params[PARAM_GET_MAX_SIZE];
+
+ ALOGV("DTS_EAGLE_HAL (%s): enter", __func__);
+
+ property_get("use.dts_eagle", prop, "0");
+ if (strncmp("true", prop, sizeof("true")))
+ return 0;
+
+ ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_DTS_EAGLE, value, sizeof(value));
+ if (ret >= 0) {
+ int *data = NULL, id = 0, size = 0, offset = 0,
+ count = 1, dev = 0, idx = 0, dts_found = 0, i = 0;
+ const size_t chars_4_int = 16;
+ ret = str_parms_get_str(query, "count", value, sizeof(value));
+ if (ret >= 0) {
+ count = atoi(value);
+ if (count > 1) {
+ ALOGV("DTS_EAGLE_HAL (%s): multi count param detected, count: %d", __func__, count);
+ } else {
+ count = 1;
+ }
+ }
+
+ ret = str_parms_get_str(query, "id", value, sizeof(value));
+ if (ret >= 0) {
+ if (sscanf(value, "%x", &id) == 1) {
+ ret = str_parms_get_str(query, "size", value, sizeof(value));
+ if (ret >= 0) {
+ size = atoi(value);
+ ret = str_parms_get_str(query, "offset", value, sizeof(value));
+ if (ret >= 0) {
+ offset = atoi(value);
+ ret = str_parms_get_str(query, "device", value, sizeof(value));
+ if (ret >= 0) {
+ dev = atoi(value);
+ dts_found = 1;
+ }
+ }
+ }
+ }
+ }
+
+ if (dts_found) {
+ ALOGI("DTS_EAGLE_HAL (%s): param (get) detected: %s", __func__, str_parms_to_str(query));
+ struct dts_eagle_param_desc_alsa *t = (struct dts_eagle_param_desc_alsa *)params;
+ if (t) {
+ char buf[chars_4_int*count];
+ t->alsa_effect_ID = DTS_EAGLE_MODULE;
+ t->d.id = id;
+ t->d.size = size;
+ t->d.offset = offset;
+ t->d.device = dev;
+ ALOGV("DTS_EAGLE_HAL (%s): id (get): 0x%X, size: %d, offset: %d, device: %d", __func__,
+ t->d.id, t->d.size, t->d.offset, t->d.device & 0x7FFFFFFF);
+ if ((sizeof(struct dts_eagle_param_desc_alsa) + size) > PARAM_GET_MAX_SIZE) {
+ ALOGE("%s: requested data too large", __func__);
+ return -1;
+ }
+ ret = do_DTS_Eagle_params(adev, t, true);
+ if (ret >= 0) {
+ data = (int*)(params + sizeof(struct dts_eagle_param_desc_alsa));
+ for (i = 0; i < count; i++)
+ idx += snprintf(&buf[idx], chars_4_int, "%i,", data[i]);
+ buf[idx > 0 ? idx-1 : 0] = 0;
+ ALOGD("DTS_EAGLE_HAL (%s): get result: %s", __func__, buf);
+ str_parms_add_int(reply, "size", size);
+ str_parms_add_str(reply, AUDIO_PARAMETER_KEY_DTS_EAGLE, buf);
+ str_parms_add_int(reply, "count", count);
+ snprintf(value, sizeof(value), "0x%x", id);
+ str_parms_add_str(reply, "id", value);
+ str_parms_add_int(reply, "device", dev);
+ str_parms_add_int(reply, "offset", offset);
+ ALOGV("DTS_EAGLE_HAL (%s): reply: %s", __func__, str_parms_to_str(reply));
+ } else {
+ ALOGE("DTS_EAGLE_HAL (%s): failed getting params from kernel with error %i", __func__, ret);
+ return -1;
+ }
+ } else {
+ ALOGE("DTS_EAGLE_HAL (%s): mem alloc for (get) dsp structure failed.", __func__);
+ return -1;
+ }
+ } else {
+ ALOGE("DTS_EAGLE_HAL (%s): param (get) detected but failed parse: %s", __func__, str_parms_to_str(query));
+ return -1;
+ }
+ }
+
+ ALOGV("DTS_EAGLE_HAL (%s): exit", __func__);
+ return 0;
+}
+
+void audio_extn_dts_create_state_notifier_node(int stream_out)
+{
+ char prop[PROPERTY_VALUE_MAX];
+ char path[PATH_MAX];
+ char value[MAX_LENGTH_OF_INTEGER_IN_STRING];
+ int fd;
+ property_get("use.dts_eagle", prop, "0");
+ if ((!strncmp("true", prop, sizeof("true")) || atoi(prop))) {
+ ALOGV("DTS_EAGLE_NODE_STREAM (%s): create_state_notifier_node - stream_out: %d", __func__, stream_out);
+ strlcpy(path, STATE_NOTIFY_FILE, sizeof(path));
+ snprintf(value, sizeof(value), "%d", stream_out);
+ strlcat(path, value, sizeof(path));
+
+ if ((fd=open(path, O_RDONLY)) < 0) {
+ ALOGV("DTS_EAGLE_NODE_STREAM (%s): no file exists", __func__);
+ } else {
+ ALOGV("DTS_EAGLE_NODE_STREAM (%s): a file with the same name exists, removing it before creating it", __func__);
+ close(fd);
+ remove(path);
+ }
+ if ((fd=creat(path, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) {
+ ALOGE("DTS_EAGLE_NODE_STREAM (%s): opening state notifier node failed returned", __func__);
+ return;
+ }
+ chmod(path, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH);
+ ALOGV("DTS_EAGLE_NODE_STREAM (%s): opening state notifier node successful", __func__);
+ close(fd);
+ }
+
+ if (!fade_in_data || !fade_out_data)
+ fade_node(true);
+}
+
+void audio_extn_dts_notify_playback_state(int stream_out, int has_video, int sample_rate,
+ int channels, int is_playing) {
+ char prop[PROPERTY_VALUE_MAX];
+ char path[PATH_MAX];
+ char value[MAX_LENGTH_OF_INTEGER_IN_STRING];
+ char buf[1024];
+ int fd;
+ property_get("use.dts_eagle", prop, "0");
+ if ((!strncmp("true", prop, sizeof("true")) || atoi(prop))) {
+ ALOGV("DTS_EAGLE_NODE_STREAM (%s): notify_playback_state - is_playing: %d", __func__, is_playing);
+ strlcpy(path, STATE_NOTIFY_FILE, sizeof(path));
+ snprintf(value, sizeof(value), "%d", stream_out);
+ strlcat(path, value, sizeof(path));
+ if ((fd=open(path, O_TRUNC|O_WRONLY)) < 0) {
+ ALOGE("DTS_EAGLE_NODE_STREAM (%s): open state notifier node failed", __func__);
+ } else {
+ snprintf(buf, sizeof(buf), "has_video=%d;sample_rate=%d;channel_mode=%d;playback_state=%d",
+ has_video, sample_rate, channels, is_playing);
+ int n = write(fd, buf, strlen(buf));
+ if (n > 0)
+ ALOGV("DTS_EAGLE_NODE_STREAM (%s): write to state notifier node successful, bytes written: %d", __func__, n);
+ else
+ ALOGE("DTS_EAGLE_NODE_STREAM (%s): write state notifier node failed", __func__);
+ close(fd);
+ }
+ }
+}
+
+void audio_extn_dts_remove_state_notifier_node(int stream_out)
+{
+ char prop[PROPERTY_VALUE_MAX];
+ char path[PATH_MAX];
+ char value[MAX_LENGTH_OF_INTEGER_IN_STRING];
+ int fd;
+ property_get("use.dts_eagle", prop, "0");
+ if ((!strncmp("true", prop, sizeof("true")) || atoi(prop)) && (stream_out)) {
+ ALOGV("DTS_EAGLE_NODE_STREAM (%s): remove_state_notifier_node: stream_out - %d", __func__, stream_out);
+ strlcpy(path, STATE_NOTIFY_FILE, sizeof(path));
+ snprintf(value, sizeof(value), "%d", stream_out);
+ strlcat(path, value, sizeof(path));
+ if ((fd=open(path, O_RDONLY)) < 0) {
+ ALOGV("DTS_EAGLE_NODE_STREAM (%s): open state notifier node failed", __func__);
+ } else {
+ ALOGV("DTS_EAGLE_NODE_STREAM (%s): open state notifier node successful, removing the file", __func__);
+ close(fd);
+ remove(path);
+ }
+ }
+}
+
+#endif /* DTS_EAGLE end */
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index 12fc5fe..34e6089 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -33,6 +33,7 @@
#include "platform.h"
#include "platform_api.h"
#include "audio_extn.h"
+#include "voice.h"
#define AUDIO_OUTPUT_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_output_policy.conf"
@@ -63,12 +64,14 @@
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER),
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD),
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING),
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_HW_AV_SYNC),
#ifdef INCALL_MUSIC_ENABLED
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_INCALL_MUSIC),
#endif
#ifdef COMPRESS_VOIP_ENABLED
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_VOIP_RX),
#endif
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH),
};
const struct string_to_enum s_format_name_to_enum_table[] = {
@@ -97,6 +100,10 @@
STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT_OFFLOAD),
STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_OFFLOAD),
STRING_TO_ENUM(AUDIO_FORMAT_FLAC),
+ STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
+ STRING_TO_ENUM(AUDIO_FORMAT_AAC_LC),
+ STRING_TO_ENUM(AUDIO_FORMAT_AAC_HE_V1),
+ STRING_TO_ENUM(AUDIO_FORMAT_AAC_HE_V2),
#endif
};
@@ -403,6 +410,7 @@
ss_info = node_to_item(node_i, struct stream_sample_rate, list);
if ((sample_rate <= ss_info->sample_rate) &&
(bit_width == so_info->app_type_cfg.bit_width)) {
+
app_type_cfg->app_type = so_info->app_type_cfg.app_type;
app_type_cfg->sample_rate = ss_info->sample_rate;
app_type_cfg->bit_width = so_info->app_type_cfg.bit_width;
@@ -508,7 +516,7 @@
(usecase->id != USECASE_AUDIO_PLAYBACK_LOW_LATENCY) &&
(usecase->id != USECASE_AUDIO_PLAYBACK_MULTI_CH) &&
(!is_offload_usecase(usecase->id))) {
- ALOGV("%s: a playback path where app type cfg is not required", __func__);
+ ALOGV("%s: a playback path where app type cfg is not required %d", __func__, usecase->id);
rc = 0;
goto exit_send_app_type_cfg;
}
@@ -547,8 +555,12 @@
app_type_cfg[len++] = out->app_type_cfg.app_type;
app_type_cfg[len++] = acdb_dev_id;
- app_type_cfg[len++] = sample_rate;
-
+ if (((out->format == AUDIO_FORMAT_E_AC3) ||
+ (out->format == AUDIO_FORMAT_E_AC3_JOC)) &&
+ (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH))
+ app_type_cfg[len++] = sample_rate * 4;
+ else
+ app_type_cfg[len++] = sample_rate;
mixer_ctl_set_array(ctl, app_type_cfg, len);
ALOGI("%s app_type %d, acdb_dev_id %d, sample_rate %d",
__func__, out->app_type_cfg.app_type, acdb_dev_id, sample_rate);
@@ -572,10 +584,18 @@
out->app_type_cfg.sample_rate);
}
if ((type == PCM_HFP_CALL) || (type == PCM_CAPTURE)) {
- /* when app type is default. the sample rate is not used to send cal */
- platform_send_audio_calibration(adev->platform, usecase->in_snd_device,
- platform_get_default_app_type(adev->platform),
- 48000);
+ if ((type == PCM_CAPTURE) & voice_is_in_call_rec_stream(usecase->stream.in)) {
+ snd_device_t incall_record_snd_device =
+ voice_get_incall_rec_snd_device(usecase->in_snd_device);
+ platform_send_audio_calibration(adev->platform, incall_record_snd_device,
+ platform_get_default_app_type(adev->platform),
+ 48000);
+ } else {
+ /* when app type is default. the sample rate is not used to send cal */
+ platform_send_audio_calibration(adev->platform, usecase->in_snd_device,
+ platform_get_default_app_type(adev->platform),
+ 48000);
+ }
}
}
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index ce26388..3750945 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -15,6 +15,24 @@
* 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.
+ *
+ * This file was modified by DTS, Inc. The portions of the
+ * code modified by DTS, Inc are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2014 DTS, Inc.
+ *
+ * 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 "audio_hw_primary"
@@ -206,7 +224,11 @@
static const struct string_to_enum out_channels_name_to_enum_table[] = {
STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
- STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
+ STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
+ STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
+ STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
+ STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
+ STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
};
@@ -677,7 +699,7 @@
/* must be called with hw device mutex locked */
static int read_hdmi_channel_masks(struct stream_out *out)
{
- int ret = 0;
+ int ret = 0, i = 0;
int channels = platform_edid_get_max_channels(out->dev->platform);
switch (channels) {
@@ -686,13 +708,21 @@
* Stereo case is handled in normal playback path
*/
case 6:
- ALOGV("%s: HDMI supports 5.1", __func__);
- out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
+ ALOGV("%s: HDMI supports Quad and 5.1", __func__);
+ out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
+ out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
+ out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
+ out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
+ out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
break;
case 8:
- ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
- out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
- out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
+ ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
+ out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
+ out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
+ out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
+ out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
+ out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
+ out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
break;
default:
ALOGE("HDMI does not support multi channel playback");
@@ -795,7 +825,9 @@
out_snd_device = platform_get_output_snd_device(adev->platform,
usecase->stream.out->devices);
if (usecase->stream.out == adev->primary_output &&
- adev->active_input) {
+ adev->active_input &&
+ adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
+ out_snd_device != usecase->out_snd_device) {
select_devices(adev, adev->active_input->usecase);
}
}
@@ -809,6 +841,7 @@
adev->active_input->source == AUDIO_SOURCE_MIC)) &&
adev->primary_output && !adev->primary_output->standby) {
out_device = adev->primary_output->devices;
+ platform_set_echo_reference(adev->platform, false);
} else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
}
@@ -966,7 +999,8 @@
if (ret)
goto error_config;
else
- ALOGV("%s: usecase(%d)", __func__, in->usecase);
+ ALOGD("%s: Updated usecase(%d: %s)",
+ __func__, in->usecase, use_case_table[in->usecase]);
in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
if (in->pcm_device_id < 0) {
@@ -992,6 +1026,7 @@
uc_info->out_snd_device = SND_DEVICE_NONE;
list_add_tail(&adev->usecase_list, &uc_info->list);
+ audio_extn_perf_lock_acquire();
select_devices(adev, in->usecase);
ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
@@ -1023,12 +1058,14 @@
}
break;
}
+ audio_extn_perf_lock_release();
ALOGV("%s: exit", __func__);
return ret;
error_open:
stop_input_stream(in);
+ audio_extn_perf_lock_release();
error_config:
adev->active_input = NULL;
@@ -1182,6 +1219,8 @@
ALOGE("%s: Next track returned error %d",__func__, ret);
send_callback = true;
event = STREAM_CBK_EVENT_DRAIN_READY;
+ /* Resend the metadata for next iteration */
+ out->send_new_metadata = 1;
break;
case OFFLOAD_CMD_DRAIN:
ALOGD("copl(%p):calling compress_drain", out);
@@ -1198,6 +1237,7 @@
out->offload_thread_blocked = false;
pthread_cond_signal(&out->cond);
if (send_callback) {
+ ALOGVV("%s: sending offload_callback event %d", __func__, event);
out->offload_callback(event, NULL, out->offload_cookie);
}
free(cmd);
@@ -1263,8 +1303,9 @@
break;
} else if (is_offload_usecase(usecase->id) &&
audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
- ALOGD("%s: multi-channel(%x) compress offload playback is active, "
- "no change in HDMI channels", __func__, usecase->stream.out->channel_mask);
+ ALOGD("%s:multi-channel(%x) compress offload playback is active"
+ ", no change in HDMI channels", __func__,
+ usecase->stream.out->channel_mask);
ret = false;
break;
}
@@ -1279,16 +1320,25 @@
struct listnode *node;
struct audio_usecase *usecase;
+ unsigned int supported_channels = platform_edid_get_max_channels(
+ adev->platform);
+ ALOGV("supported_channels %d, channels %d", supported_channels, channels);
/* Check if change in HDMI channel config is allowed */
if (!allow_hdmi_channel_config(adev))
return 0;
+ if (channels > supported_channels)
+ channels = supported_channels;
+
if (channels == adev->cur_hdmi_channels) {
- ALOGD("%s: Requested channels are same as current channels(%d)", __func__, channels);
+ ALOGD("%s: Requested channels are same as current channels(%d)",
+ __func__, channels);
return 0;
}
+ /*TODO: CHECK for passthrough don't set channel map for passthrough*/
platform_set_hdmi_channels(adev->platform, channels);
+ platform_set_edid_channels_configuration(adev->platform, channels);
adev->cur_hdmi_channels = channels;
/*
@@ -1334,9 +1384,13 @@
return -EINVAL;
}
- if (is_offload_usecase(out->usecase)) {
+ if (is_offload_usecase(out->usecase) &&
+ !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
if (adev->visualizer_stop_output != NULL)
adev->visualizer_stop_output(out->handle, out->pcm_device_id);
+
+ audio_extn_dts_remove_state_notifier_node(out->usecase);
+
if (adev->offload_effects_stop_output != NULL)
adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
}
@@ -1350,6 +1404,15 @@
list_remove(&uc_info->list);
free(uc_info);
+ if (is_offload_usecase(out->usecase) &&
+ (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
+ (audio_extn_dolby_is_passthrough_stream(out->flags))) {
+ ALOGV("Disable passthrough , reset mixer to pcm");
+ /* NO_PASSTHROUGH */
+ out->compr_config.codec->compr_passthr = 0;
+ audio_extn_dolby_set_hdmi_config(adev, out);
+ audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
+ }
/* Must be called after removing the usecase from list */
if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
@@ -1387,7 +1450,7 @@
ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
__func__, out->pcm_device_id, out->usecase);
ret = -EINVAL;
- goto error_config;
+ goto error_open;
}
uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
@@ -1403,22 +1466,31 @@
uc_info->devices = out->devices;
uc_info->in_snd_device = SND_DEVICE_NONE;
uc_info->out_snd_device = SND_DEVICE_NONE;
-
/* This must be called before adding this usecase to the list */
if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
+ if (is_offload_usecase(out->usecase)) {
+ if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
+ audio_extn_dolby_update_passt_stream_configuration(adev, out);
+ }
+ }
property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
if (!strncmp("true", prop_value, 4)) {
sink_channels = platform_edid_get_max_channels(out->dev->platform);
- ALOGD("%s: set HDMI channel count[%d] based on sink capability", __func__, sink_channels);
+ ALOGD("%s: set HDMI channel count[%d] based on sink capability",
+ __func__, sink_channels);
check_and_set_hdmi_channels(adev, sink_channels);
} else {
- if (is_offload_usecase(out->usecase))
- check_and_set_hdmi_channels(adev, out->compr_config.codec->ch_in);
- else
+ if (is_offload_usecase(out->usecase)) {
+ unsigned int ch_count = out->compr_config.codec->ch_in;
+ if (audio_extn_dolby_is_passthrough_stream(out->flags))
+ /* backend channel config for passthrough stream is stereo */
+ ch_count = 2;
+ check_and_set_hdmi_channels(adev, ch_count);
+ } else
check_and_set_hdmi_channels(adev, out->config.channels);
}
+ audio_extn_dolby_set_hdmi_config(adev, out);
}
-
list_add_tail(&adev->usecase_list, &uc_info->list);
select_devices(adev, out->usecase);
@@ -1452,7 +1524,11 @@
}
break;
}
+ platform_set_stream_channel_map(adev->platform, out->channel_mask,
+ out->pcm_device_id);
} else {
+ platform_set_stream_channel_map(adev->platform, out->channel_mask,
+ out->pcm_device_id);
out->pcm = NULL;
out->compr = compress_open(adev->snd_card,
out->pcm_device_id,
@@ -1467,15 +1543,22 @@
if (out->offload_callback)
compress_nonblock(out->compr, out->non_blocking);
+ audio_extn_dts_create_state_notifier_node(out->usecase);
+ audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
+ popcount(out->channel_mask),
+ out->playback_started);
+
#ifdef DS1_DOLBY_DDP_ENABLED
if (audio_extn_is_dolby_format(out->format))
audio_extn_dolby_send_ddp_endp_params(adev);
#endif
-
- if (adev->visualizer_start_output != NULL)
- adev->visualizer_start_output(out->handle, out->pcm_device_id);
- if (adev->offload_effects_start_output != NULL)
- adev->offload_effects_start_output(out->handle, out->pcm_device_id);
+ if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
+ if (adev->visualizer_start_output != NULL)
+ adev->visualizer_start_output(out->handle, out->pcm_device_id);
+ if (adev->offload_effects_start_output != NULL)
+ adev->offload_effects_start_output(out->handle, out->pcm_device_id);
+ audio_extn_check_and_set_dts_hpx_state(adev);
+ }
}
ALOGV("%s: exit", __func__);
return 0;
@@ -1759,7 +1842,8 @@
if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
val == AUDIO_DEVICE_NONE) {
- val = AUDIO_DEVICE_OUT_SPEAKER;
+ if (!audio_extn_dolby_is_passthrough_stream(out->flags))
+ val = AUDIO_DEVICE_OUT_SPEAKER;
}
/*
@@ -1811,6 +1895,12 @@
if (is_offload_usecase(out->usecase)) {
pthread_mutex_lock(&out->lock);
parse_compress_metadata(out, parms);
+
+ audio_extn_dts_create_state_notifier_node(out->usecase);
+ audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
+ popcount(out->channel_mask),
+ out->playback_started);
+
pthread_mutex_unlock(&out->lock);
}
@@ -1864,6 +1954,28 @@
str = strdup(keys);
}
}
+
+ ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
+ if (ret >= 0) {
+ value[0] = '\0';
+ i = 0;
+ first = true;
+ while (out->supported_formats[i] != 0) {
+ for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
+ if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
+ if (!first) {
+ strcat(value, "|");
+ }
+ strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
+ first = false;
+ break;
+ }
+ }
+ i++;
+ }
+ str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
+ str = str_parms_to_str(reply);
+ }
str_parms_destroy(query);
str_parms_destroy(reply);
ALOGV("%s: exit: returns - %s", __func__, str);
@@ -1873,12 +1985,23 @@
static uint32_t out_get_latency(const struct audio_stream_out *stream)
{
struct stream_out *out = (struct stream_out *)stream;
+ uint32_t latency = 0;
- if (is_offload_usecase(out->usecase))
- return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
-
- return (out->config.period_count * out->config.period_size * 1000) /
+ if (is_offload_usecase(out->usecase)) {
+ if (out->use_small_bufs == true)
+ latency = ((out->compr_config.fragments *
+ out->compr_config.fragment_size * 1000) /
+ (out->sample_rate * out->compr_config.codec->ch_in *
+ audio_bytes_per_sample(out->format)));
+ else
+ latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
+ } else {
+ latency = (out->config.period_count * out->config.period_size * 1000) /
(out->config.rate);
+ }
+
+ ALOGV("%s: Latency %d", __func__, latency);
+ return latency;
}
static int out_set_volume(struct audio_stream_out *stream, float left,
@@ -1892,24 +2015,33 @@
out->muted = (left == 0.0f);
return 0;
} else if (is_offload_usecase(out->usecase)) {
- char mixer_ctl_name[128];
- struct audio_device *adev = out->dev;
- struct mixer_ctl *ctl;
- int pcm_device_id = platform_get_pcm_device_id(out->usecase,
+ if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
+ /*
+ * Set mute or umute on HDMI passthrough stream.
+ * Only take left channel into account.
+ * Mute is 0 and unmute 1
+ */
+ audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
+ } else {
+ char mixer_ctl_name[128];
+ struct audio_device *adev = out->dev;
+ struct mixer_ctl *ctl;
+ int pcm_device_id = platform_get_pcm_device_id(out->usecase,
PCM_PLAYBACK);
- snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
- "Compress Playback %d Volume", pcm_device_id);
- ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
- if (!ctl) {
- ALOGE("%s: Could not get ctl for mixer cmd - %s",
- __func__, mixer_ctl_name);
- return -EINVAL;
+ snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+ "Compress Playback %d Volume", pcm_device_id);
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",
+ __func__, mixer_ctl_name);
+ return -EINVAL;
+ }
+ volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
+ volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
+ mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
+ return 0;
}
- volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
- volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
- mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
- return 0;
}
return -ENOSYS;
@@ -1979,6 +2111,10 @@
compress_start(out->compr);
out->playback_started = 1;
out->offload_state = OFFLOAD_STATE_PLAYING;
+
+ audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
+ popcount(out->channel_mask),
+ out->playback_started);
}
pthread_mutex_unlock(&out->lock);
return ret;
@@ -2147,6 +2283,11 @@
status = compress_pause(out->compr);
out->offload_state = OFFLOAD_STATE_PAUSED;
+
+ audio_extn_dts_eagle_fade(adev, false);
+ audio_extn_dts_notify_playback_state(out->usecase, 0,
+ out->sample_rate, popcount(out->channel_mask),
+ 0);
}
pthread_mutex_unlock(&out->lock);
}
@@ -2170,6 +2311,10 @@
status = compress_resume(out->compr);
out->offload_state = OFFLOAD_STATE_PLAYING;
+
+ audio_extn_dts_eagle_fade(adev, true);
+ audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
+ popcount(out->channel_mask), 1);
}
pthread_mutex_unlock(&out->lock);
}
@@ -2439,7 +2584,8 @@
* Instead of writing zeroes here, we could trust the hardware
* to always provide zeroes when muted.
*/
- if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in))
+ if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
+ in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
memset(buffer, 0, bytes);
exit:
@@ -2562,6 +2708,8 @@
out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
out->handle = handle;
out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
+ out->non_blocking = 0;
+ out->use_small_bufs = false;
/* Init use case and pcm_config */
if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
@@ -2606,6 +2754,18 @@
ret = -EINVAL;
goto error_open;
}
+
+ if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
+ ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
+ ALOGV("read and update_pass through formats");
+ ret = audio_extn_dolby_update_passt_formats(adev, out);
+ if(ret != 0) {
+ goto error_open;
+ }
+ if(config->offload_info.format == 0)
+ config->offload_info.format = out->supported_formats[0];
+ }
+
if (!is_supported_format(config->offload_info.format) &&
!audio_extn_is_dolby_format(config->offload_info.format)) {
ALOGE("%s: Unsupported audio format", __func__);
@@ -2647,10 +2807,13 @@
get_snd_codec_id(config->offload_info.format);
if (audio_is_offload_pcm(config->offload_info.format)) {
out->compr_config.fragment_size =
- platform_get_pcm_offload_buffer_size(&config->offload_info);
+ platform_get_pcm_offload_buffer_size(&config->offload_info);
+ } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
+ out->compr_config.fragment_size =
+ audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
} else {
out->compr_config.fragment_size =
- platform_get_compress_offload_buffer_size(&config->offload_info);
+ platform_get_compress_offload_buffer_size(&config->offload_info);
}
out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
out->compr_config.codec->sample_rate =
@@ -2661,6 +2824,8 @@
audio_channel_count_from_out_mask(config->channel_mask);
out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
out->bit_width = PCM_OUTPUT_BIT_WIDTH;
+ /*TODO: Do we need to change it for passthrough */
+ out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
if (config->offload_info.format == AUDIO_FORMAT_AAC)
out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
@@ -2679,17 +2844,27 @@
if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
out->non_blocking = 1;
+ if (config->offload_info.use_small_bufs) {
+ //this flag is set from framework only if its for PCM formats
+ //no need to check for PCM format again
+ out->non_blocking = 0;
+ out->use_small_bufs = true;
+ ALOGI("Keep write blocking for small buff: non_blockling %d",
+ out->non_blocking);
+ }
+
out->send_new_metadata = 1;
out->offload_state = OFFLOAD_STATE_IDLE;
out->playback_started = 0;
+ audio_extn_dts_create_state_notifier_node(out->usecase);
+
create_offload_callback_thread(out);
ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
__func__, config->offload_info.version,
config->offload_info.bit_rate);
//Decide if we need to use gapless mode by default
check_and_set_gapless_mode(adev);
-
} else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
ret = voice_check_and_set_incall_music_usecase(adev, out);
if (ret != 0) {
@@ -2734,6 +2909,9 @@
ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
__func__, devices, flags, format, out->sample_rate, out->bit_width);
+ /* TODO remove this hardcoding and check why width is zero*/
+ if (out->bit_width == 0)
+ out->bit_width = 16;
audio_extn_utils_update_stream_app_type_cfg(adev->platform,
&adev->streams_output_cfg_list,
devices, flags, format, out->sample_rate,
@@ -2794,6 +2972,11 @@
*stream_out = &out->stream;
ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
use_case_table[out->usecase]);
+
+ if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
+ audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
+ popcount(out->channel_mask), out->playback_started);
+
ALOGV("%s: exit", __func__);
return 0;
@@ -2824,6 +3007,7 @@
out_standby(&stream->common);
if (is_offload_usecase(out->usecase)) {
+ audio_extn_dts_remove_state_notifier_node(out->usecase);
destroy_offload_callback_thread(out);
free_offload_usecase(adev, out->usecase);
if (out->compr_config.codec != NULL)
@@ -2961,6 +3145,24 @@
adev->bt_wb_speech_enabled = false;
}
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
+ if (ret >= 0) {
+ val = atoi(value);
+ if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
+ ALOGV("cache new edid");
+ platform_cache_edid(adev->platform);
+ }
+ }
+
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
+ if (ret >= 0) {
+ val = atoi(value);
+ if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
+ ALOGV("invalidate cached edid");
+ platform_invalidate_edid(adev->platform);
+ }
+ }
+
audio_extn_set_parameters(adev, parms);
done:
@@ -3167,6 +3369,10 @@
in->format = config->format;
if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
+ if (adev->mode != AUDIO_MODE_IN_CALL) {
+ ret = -EINVAL;
+ goto err_open;
+ }
if (config->sample_rate == 0)
config->sample_rate = AFE_PROXY_SAMPLING_RATE;
if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
@@ -3214,6 +3420,7 @@
/* This stream could be for sound trigger lab,
get sound trigger pcm if present */
audio_extn_sound_trigger_check_and_get_session(in);
+ audio_extn_perf_lock_init();
*stream_in = &in->stream;
ALOGV("%s: exit", __func__);
@@ -3418,6 +3625,9 @@
adev->offload_effects_stop_output =
(int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
"offload_effects_bundle_hal_stop_output");
+ adev->offload_effects_set_hpx_state =
+ (int (*)(bool))dlsym(adev->offload_effects_lib,
+ "offload_effects_bundle_set_hpx_state");
}
}
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index d05f743..ba24b6b 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -15,6 +15,24 @@
* 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.
+ *
+ * This file was modified by DTS, Inc. The portions of the
+ * code modified by DTS, Inc are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2014 DTS, Inc.
+ *
+ * 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.
*/
#ifndef QCOM_AUDIO_HW_H
@@ -47,12 +65,12 @@
#define ACDB_DEV_TYPE_OUT 1
#define ACDB_DEV_TYPE_IN 2
-#define MAX_SUPPORTED_CHANNEL_MASKS 2
+#define MAX_SUPPORTED_CHANNEL_MASKS 8
+#define MAX_SUPPORTED_FORMATS 3
#define DEFAULT_HDMI_OUT_CHANNELS 2
#define SND_CARD_STATE_OFFLINE 0
#define SND_CARD_STATE_ONLINE 1
-typedef int snd_device_t;
/* These are the supported use cases by the hardware.
* Each usecase is mapped to a specific PCM device.
@@ -174,12 +192,14 @@
audio_usecase_t usecase;
/* Array of supported channel mask configurations. +1 so that the last entry is always 0 */
audio_channel_mask_t supported_channel_masks[MAX_SUPPORTED_CHANNEL_MASKS + 1];
+ audio_format_t supported_formats[MAX_SUPPORTED_FORMATS+1];
bool muted;
uint64_t written; /* total frames written, not cleared when entering standby */
audio_io_handle_t handle;
struct stream_app_type_cfg app_type_cfg;
int non_blocking;
+ bool use_small_bufs;
int playback_started;
int offload_state;
pthread_cond_t offload_cond;
@@ -298,6 +318,7 @@
int (*offload_effects_stop_output)(audio_io_handle_t, int);
struct sound_card_status snd_card_status;
+ int (*offload_effects_set_hpx_state)(bool);
};
int select_devices(struct audio_device *adev,
diff --git a/hal/edid.c b/hal/edid.c
new file mode 100644
index 0000000..9b05950
--- /dev/null
+++ b/hal/edid.c
@@ -0,0 +1,687 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright (C) 2014 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 "audio_hw_edid"
+/*#define LOG_NDEBUG 0*/
+/*#define LOG_NDDEBUG 0*/
+
+#include <errno.h>
+#include <cutils/properties.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <cutils/str_parms.h>
+#include <cutils/log.h>
+
+#include "audio_hw.h"
+#include "platform.h"
+#include "platform_api.h"
+#include "edid.h"
+
+static const char * edid_format_to_str(unsigned char format)
+{
+ char * format_str = "??";
+
+ switch (format) {
+ case LPCM:
+ format_str = "Format:LPCM";
+ break;
+ case AC3:
+ format_str = "Format:AC-3";
+ break;
+ case MPEG1:
+ format_str = "Format:MPEG1 (Layers 1 & 2)";
+ break;
+ case MP3:
+ format_str = "Format:MP3 (MPEG1 Layer 3)";
+ break;
+ case MPEG2_MULTI_CHANNEL:
+ format_str = "Format:MPEG2 (multichannel)";
+ break;
+ case AAC:
+ format_str = "Format:AAC";
+ break;
+ case DTS:
+ format_str = "Format:DTS";
+ break;
+ case ATRAC:
+ format_str = "Format:ATRAC";
+ break;
+ case SACD:
+ format_str = "Format:One-bit audio aka SACD";
+ break;
+ case DOLBY_DIGITAL_PLUS:
+ format_str = "Format:Dolby Digital +";
+ break;
+ case DTS_HD:
+ format_str = "Format:DTS-HD";
+ break;
+ case MAT:
+ format_str = "Format:MAT (MLP)";
+ break;
+ case DST:
+ format_str = "Format:DST";
+ break;
+ case WMA_PRO:
+ format_str = "Format:WMA Pro";
+ break;
+ default:
+ break;
+ }
+ return format_str;
+}
+
+static int get_edid_sf(unsigned char byte)
+{
+ int nfreq = 0;
+
+ if (byte & BIT(6)) {
+ ALOGV("192kHz");
+ nfreq = 192000;
+ } else if (byte & BIT(5)) {
+ ALOGV("176kHz");
+ nfreq = 176000;
+ } else if (byte & BIT(4)) {
+ ALOGV("96kHz");
+ nfreq = 96000;
+ } else if (byte & BIT(3)) {
+ ALOGV("88.2kHz");
+ nfreq = 88200;
+ } else if (byte & BIT(2)) {
+ ALOGV("48kHz");
+ nfreq = 48000;
+ } else if (byte & BIT(1)) {
+ ALOGV("44.1kHz");
+ nfreq = 44100;
+ } else if (byte & BIT(0)) {
+ ALOGV("32kHz");
+ nfreq = 32000;
+ }
+ return nfreq;
+}
+
+static int get_edid_bps(unsigned char byte,
+ unsigned char format)
+{
+ int bits_per_sample = 0;
+ if (format == 1) {
+ if (byte & BIT(2)) {
+ ALOGV("24bit");
+ bits_per_sample = 24;
+ } else if (byte & BIT(1)) {
+ ALOGV("20bit");
+ bits_per_sample = 20;
+ } else if (byte & BIT(0)) {
+ ALOGV("16bit");
+ bits_per_sample = 16;
+ }
+ } else {
+ ALOGV("not lpcm format, return 0");
+ return 0;
+ }
+ return bits_per_sample;
+}
+
+static void update_channel_map(edid_audio_info* info)
+{
+ /* HDMI Cable follows CEA standard so SAD is received in CEA
+ * Input source file channel map is fed to ASM in WAV standard(audio.h)
+ * so upto 7.1 SAD bits are:
+ * in CEA convention: RLC/RRC,FLC/FRC,RC,RL/RR,FC,LFE,FL/FR
+ * in WAV convention: BL/BR,FLC/FRC,BC,SL/SR,FC,LFE,FL/FR
+ * Corresponding ADSP IDs (apr-audio_v2.h):
+ * PCM_CHANNEL_FL/PCM_CHANNEL_FR,
+ * PCM_CHANNEL_LFE,
+ * PCM_CHANNEL_FC,
+ * PCM_CHANNEL_LS/PCM_CHANNEL_RS,
+ * PCM_CHANNEL_CS,
+ * PCM_CHANNEL_FLC/PCM_CHANNEL_FRC
+ * PCM_CHANNEL_LB/PCM_CHANNEL_RB
+ */
+ if (!info)
+ return;
+ memset(info->channel_map, 0, MAX_CHANNELS_SUPPORTED);
+ if(info->speaker_allocation[0] & BIT(0)) {
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ }
+ if(info->speaker_allocation[0] & BIT(1)) {
+ info->channel_map[2] = PCM_CHANNEL_LFE;
+ }
+ if(info->speaker_allocation[0] & BIT(2)) {
+ info->channel_map[3] = PCM_CHANNEL_FC;
+ }
+ if(info->speaker_allocation[0] & BIT(3)) {
+ /*
+ * As per CEA(HDMI Cable) standard Bit 3 is equivalent
+ * to SideLeft/SideRight of WAV standard
+ */
+ info->channel_map[4] = PCM_CHANNEL_LS;
+ info->channel_map[5] = PCM_CHANNEL_RS;
+ }
+ if(info->speaker_allocation[0] & BIT(4)) {
+ if(info->speaker_allocation[0] & BIT(3)) {
+ info->channel_map[6] = PCM_CHANNEL_CS;
+ info->channel_map[7] = 0;
+ } else if (info->speaker_allocation[1] & BIT(1)) {
+ info->channel_map[6] = PCM_CHANNEL_CS;
+ info->channel_map[7] = PCM_CHANNEL_TS;
+ } else if (info->speaker_allocation[1] & BIT(2)) {
+ info->channel_map[6] = PCM_CHANNEL_CS;
+ info->channel_map[7] = PCM_CHANNEL_CVH;
+ } else {
+ info->channel_map[4] = PCM_CHANNEL_CS;
+ info->channel_map[5] = 0;
+ }
+ }
+ if(info->speaker_allocation[0] & BIT(5)) {
+ info->channel_map[6] = PCM_CHANNEL_FLC;
+ info->channel_map[7] = PCM_CHANNEL_FRC;
+ }
+ if(info->speaker_allocation[0] & BIT(6)) {
+ // If RLC/RRC is present, RC is invalid as per specification
+ info->speaker_allocation[0] &= 0xef;
+ /*
+ * As per CEA(HDMI Cable) standard Bit 6 is equivalent
+ * to BackLeft/BackRight of WAV standard
+ */
+ info->channel_map[6] = PCM_CHANNEL_LB;
+ info->channel_map[7] = PCM_CHANNEL_RB;
+ }
+ // higher channel are not defined by LPASS
+ //info->nSpeakerAllocation[0] &= 0x3f;
+ if(info->speaker_allocation[0] & BIT(7)) {
+ info->channel_map[6] = 0; // PCM_CHANNEL_FLW; but not defined by LPASS
+ info->channel_map[7] = 0; // PCM_CHANNEL_FRW; but not defined by LPASS
+ }
+ if(info->speaker_allocation[1] & BIT(0)) {
+ info->channel_map[6] = 0; // PCM_CHANNEL_FLH; but not defined by LPASS
+ info->channel_map[7] = 0; // PCM_CHANNEL_FRH; but not defined by LPASS
+ }
+
+ ALOGI("%s channel map updated to [%d %d %d %d %d %d %d %d ] [%x %x %x]", __func__
+ , info->channel_map[0], info->channel_map[1], info->channel_map[2]
+ , info->channel_map[3], info->channel_map[4], info->channel_map[5]
+ , info->channel_map[6], info->channel_map[7]
+ , info->speaker_allocation[0], info->speaker_allocation[1]
+ , info->speaker_allocation[2]);
+}
+
+static void dump_speaker_allocation(edid_audio_info* info)
+{
+ if (!info)
+ return;
+
+ if (info->speaker_allocation[0] & BIT(7))
+ ALOGV("FLW/FRW");
+ if (info->speaker_allocation[0] & BIT(6))
+ ALOGV("RLC/RRC");
+ if (info->speaker_allocation[0] & BIT(5))
+ ALOGV("FLC/FRC");
+ if (info->speaker_allocation[0] & BIT(4))
+ ALOGV("RC");
+ if (info->speaker_allocation[0] & BIT(3))
+ ALOGV("RL/RR");
+ if (info->speaker_allocation[0] & BIT(2))
+ ALOGV("FC");
+ if (info->speaker_allocation[0] & BIT(1))
+ ALOGV("LFE");
+ if (info->speaker_allocation[0] & BIT(0))
+ ALOGV("FL/FR");
+ if (info->speaker_allocation[1] & BIT(2))
+ ALOGV("FCH");
+ if (info->speaker_allocation[1] & BIT(1))
+ ALOGV("TC");
+ if (info->speaker_allocation[1] & BIT(0))
+ ALOGV("FLH/FRH");
+}
+
+static void update_channel_allocation(edid_audio_info* info)
+{
+ int16_t ca;
+ int16_t spkr_alloc;
+
+ if (!info)
+ return;
+
+ /* Most common 5.1 SAD is 0xF, ca 0x0b
+ * and 7.1 SAD is 0x4F, ca 0x13 */
+ spkr_alloc = ((info->speaker_allocation[1]) << 8) |
+ (info->speaker_allocation[0]);
+ ALOGV("info->nSpeakerAllocation %x %x\n", info->speaker_allocation[0],
+ info->speaker_allocation[1]);
+ ALOGV("spkr_alloc: %x", spkr_alloc);
+
+ /* The below switch case calculates channel allocation values
+ as defined in CEA-861 section 6.6.2 */
+ switch (spkr_alloc) {
+ case BIT(0): ca = 0x00; break;
+ case BIT(0)|BIT(1): ca = 0x01; break;
+ case BIT(0)|BIT(2): ca = 0x02; break;
+ case BIT(0)|BIT(1)|BIT(2): ca = 0x03; break;
+ case BIT(0)|BIT(4): ca = 0x04; break;
+ case BIT(0)|BIT(1)|BIT(4): ca = 0x05; break;
+ case BIT(0)|BIT(2)|BIT(4): ca = 0x06; break;
+ case BIT(0)|BIT(1)|BIT(2)|BIT(4): ca = 0x07; break;
+ case BIT(0)|BIT(3): ca = 0x08; break;
+ case BIT(0)|BIT(1)|BIT(3): ca = 0x09; break;
+ case BIT(0)|BIT(2)|BIT(3): ca = 0x0A; break;
+ case BIT(0)|BIT(1)|BIT(2)|BIT(3): ca = 0x0B; break;
+ case BIT(0)|BIT(3)|BIT(4): ca = 0x0C; break;
+ case BIT(0)|BIT(1)|BIT(3)|BIT(4): ca = 0x0D; break;
+ case BIT(0)|BIT(2)|BIT(3)|BIT(4): ca = 0x0E; break;
+ case BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4): ca = 0x0F; break;
+ case BIT(0)|BIT(3)|BIT(6): ca = 0x10; break;
+ case BIT(0)|BIT(1)|BIT(3)|BIT(6): ca = 0x11; break;
+ case BIT(0)|BIT(2)|BIT(3)|BIT(6): ca = 0x12; break;
+ case BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(6): ca = 0x13; break;
+ case BIT(0)|BIT(5): ca = 0x14; break;
+ case BIT(0)|BIT(1)|BIT(5): ca = 0x15; break;
+ case BIT(0)|BIT(2)|BIT(5): ca = 0x16; break;
+ case BIT(0)|BIT(1)|BIT(2)|BIT(5): ca = 0x17; break;
+ case BIT(0)|BIT(4)|BIT(5): ca = 0x18; break;
+ case BIT(0)|BIT(1)|BIT(4)|BIT(5): ca = 0x19; break;
+ case BIT(0)|BIT(2)|BIT(4)|BIT(5): ca = 0x1A; break;
+ case BIT(0)|BIT(1)|BIT(2)|BIT(4)|BIT(5): ca = 0x1B; break;
+ case BIT(0)|BIT(3)|BIT(5): ca = 0x1C; break;
+ case BIT(0)|BIT(1)|BIT(3)|BIT(5): ca = 0x1D; break;
+ case BIT(0)|BIT(2)|BIT(3)|BIT(5): ca = 0x1E; break;
+ case BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(5): ca = 0x1F; break;
+ case BIT(0)|BIT(2)|BIT(3)|BIT(10): ca = 0x20; break;
+ case BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(10): ca = 0x21; break;
+ case BIT(0)|BIT(2)|BIT(3)|BIT(9): ca = 0x22; break;
+ case BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(9): ca = 0x23; break;
+ case BIT(0)|BIT(3)|BIT(8): ca = 0x24; break;
+ case BIT(0)|BIT(1)|BIT(3)|BIT(8): ca = 0x25; break;
+ case BIT(0)|BIT(3)|BIT(7): ca = 0x26; break;
+ case BIT(0)|BIT(1)|BIT(3)|BIT(7): ca = 0x27; break;
+ case BIT(0)|BIT(2)|BIT(3)|BIT(4)|BIT(9): ca = 0x28; break;
+ case BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4)|BIT(9): ca = 0x29; break;
+ case BIT(0)|BIT(2)|BIT(3)|BIT(4)|BIT(10): ca = 0x2A; break;
+ case BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4)|BIT(10): ca = 0x2B; break;
+ case BIT(0)|BIT(2)|BIT(3)|BIT(9)|BIT(10): ca = 0x2C; break;
+ case BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(9)|BIT(10): ca = 0x2D; break;
+ case BIT(0)|BIT(2)|BIT(3)|BIT(8): ca = 0x2E; break;
+ case BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(8): ca = 0x2F; break;
+ case BIT(0)|BIT(2)|BIT(3)|BIT(7): ca = 0x30; break;
+ case BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(7): ca = 0x31; break;
+ default: ca = 0x0; break;
+ }
+ ALOGD("%s channel allocation: %x", __func__, ca);
+ info->channel_allocation = ca;
+}
+
+static void update_channel_map_lpass(edid_audio_info* info)
+{
+ if (!info)
+ return;
+ if (info->channel_allocation < 0 || info->channel_allocation > 0x1f) {
+ ALOGE("Channel allocation out of supported range");
+ return;
+ }
+ ALOGV("channel_allocation 0x%x", info->channel_allocation);
+ memset(info->channel_map, 0, MAX_CHANNELS_SUPPORTED);
+ switch(info->channel_allocation) {
+ case 0x0:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ break;
+ case 0x1:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_LFE;
+ break;
+ case 0x2:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_FC;
+ break;
+ case 0x3:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_LFE;
+ info->channel_map[3] = PCM_CHANNEL_FC;
+ break;
+ case 0x4:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_CS;
+ break;
+ case 0x5:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_LFE;
+ info->channel_map[3] = PCM_CHANNEL_CS;
+ break;
+ case 0x6:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_FC;
+ info->channel_map[3] = PCM_CHANNEL_CS;
+ break;
+ case 0x7:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_LFE;
+ info->channel_map[3] = PCM_CHANNEL_FC;
+ info->channel_map[4] = PCM_CHANNEL_CS;
+ break;
+ case 0x8:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_LS;
+ info->channel_map[3] = PCM_CHANNEL_RS;
+ break;
+ case 0x9:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_LFE;
+ info->channel_map[3] = PCM_CHANNEL_LS;
+ info->channel_map[4] = PCM_CHANNEL_RS;
+ break;
+ case 0xa:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_FC;
+ info->channel_map[3] = PCM_CHANNEL_LS;
+ info->channel_map[4] = PCM_CHANNEL_RS;
+ break;
+ case 0xb:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_LFE;
+ info->channel_map[3] = PCM_CHANNEL_FC;
+ info->channel_map[4] = PCM_CHANNEL_LS;
+ info->channel_map[5] = PCM_CHANNEL_RS;
+ break;
+ case 0xc:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_LS;
+ info->channel_map[3] = PCM_CHANNEL_RS;
+ info->channel_map[4] = PCM_CHANNEL_CS;
+ break;
+ case 0xd:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_LFE;
+ info->channel_map[3] = PCM_CHANNEL_LS;
+ info->channel_map[4] = PCM_CHANNEL_RS;
+ info->channel_map[5] = PCM_CHANNEL_CS;
+ break;
+ case 0xe:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_FC;
+ info->channel_map[3] = PCM_CHANNEL_LS;
+ info->channel_map[4] = PCM_CHANNEL_RS;
+ info->channel_map[5] = PCM_CHANNEL_CS;
+ break;
+ case 0xf:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_LFE;
+ info->channel_map[3] = PCM_CHANNEL_FC;
+ info->channel_map[4] = PCM_CHANNEL_LS;
+ info->channel_map[5] = PCM_CHANNEL_RS;
+ info->channel_map[6] = PCM_CHANNEL_CS;
+ break;
+ case 0x10:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_LS;
+ info->channel_map[3] = PCM_CHANNEL_RS;
+ info->channel_map[4] = PCM_CHANNEL_LB;
+ info->channel_map[5] = PCM_CHANNEL_RB;
+ break;
+ case 0x11:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_LFE;
+ info->channel_map[3] = PCM_CHANNEL_LS;
+ info->channel_map[4] = PCM_CHANNEL_RS;
+ info->channel_map[5] = PCM_CHANNEL_LB;
+ info->channel_map[6] = PCM_CHANNEL_RB;
+ break;
+ case 0x12:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_FC;
+ info->channel_map[3] = PCM_CHANNEL_LS;
+ info->channel_map[4] = PCM_CHANNEL_RS;
+ info->channel_map[5] = PCM_CHANNEL_LB;
+ info->channel_map[6] = PCM_CHANNEL_RB;
+ break;
+ case 0x13:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_LFE;
+ info->channel_map[3] = PCM_CHANNEL_FC;
+ info->channel_map[4] = PCM_CHANNEL_LS;
+ info->channel_map[5] = PCM_CHANNEL_RS;
+ info->channel_map[6] = PCM_CHANNEL_LB;
+ info->channel_map[7] = PCM_CHANNEL_RB;
+ break;
+ case 0x14:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_FLC;
+ info->channel_map[3] = PCM_CHANNEL_FRC;
+ break;
+ case 0x15:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_LFE;
+ info->channel_map[3] = PCM_CHANNEL_FLC;
+ info->channel_map[4] = PCM_CHANNEL_FRC;
+ break;
+ case 0x16:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_FC;
+ info->channel_map[3] = PCM_CHANNEL_FLC;
+ info->channel_map[4] = PCM_CHANNEL_FRC;
+ break;
+ case 0x17:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_LFE;
+ info->channel_map[3] = PCM_CHANNEL_FC;
+ info->channel_map[4] = PCM_CHANNEL_FLC;
+ info->channel_map[5] = PCM_CHANNEL_FRC;
+ break;
+ case 0x18:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_CS;
+ info->channel_map[3] = PCM_CHANNEL_FLC;
+ info->channel_map[4] = PCM_CHANNEL_FRC;
+ break;
+ case 0x19:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_LFE;
+ info->channel_map[3] = PCM_CHANNEL_CS;
+ info->channel_map[4] = PCM_CHANNEL_FLC;
+ info->channel_map[5] = PCM_CHANNEL_FRC;
+ break;
+ case 0x1a:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_FC;
+ info->channel_map[3] = PCM_CHANNEL_CS;
+ info->channel_map[4] = PCM_CHANNEL_FLC;
+ info->channel_map[5] = PCM_CHANNEL_FRC;
+ break;
+ case 0x1b:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_LFE;
+ info->channel_map[3] = PCM_CHANNEL_FC;
+ info->channel_map[4] = PCM_CHANNEL_CS;
+ info->channel_map[5] = PCM_CHANNEL_FLC;
+ info->channel_map[6] = PCM_CHANNEL_FRC;
+ break;
+ case 0x1c:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_LS;
+ info->channel_map[3] = PCM_CHANNEL_RS;
+ info->channel_map[4] = PCM_CHANNEL_FLC;
+ info->channel_map[5] = PCM_CHANNEL_FRC;
+ break;
+ case 0x1d:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_LFE;
+ info->channel_map[3] = PCM_CHANNEL_LS;
+ info->channel_map[4] = PCM_CHANNEL_RS;
+ info->channel_map[5] = PCM_CHANNEL_FLC;
+ info->channel_map[6] = PCM_CHANNEL_FRC;
+ break;
+ case 0x1e:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_FC;
+ info->channel_map[3] = PCM_CHANNEL_LS;
+ info->channel_map[4] = PCM_CHANNEL_RS;
+ info->channel_map[5] = PCM_CHANNEL_FLC;
+ info->channel_map[6] = PCM_CHANNEL_FRC;
+ break;
+ case 0x1f:
+ info->channel_map[0] = PCM_CHANNEL_FL;
+ info->channel_map[1] = PCM_CHANNEL_FR;
+ info->channel_map[2] = PCM_CHANNEL_LFE;
+ info->channel_map[3] = PCM_CHANNEL_FC;
+ info->channel_map[4] = PCM_CHANNEL_LS;
+ info->channel_map[5] = PCM_CHANNEL_RS;
+ info->channel_map[6] = PCM_CHANNEL_FLC;
+ info->channel_map[7] = PCM_CHANNEL_FRC;
+ break;
+ default:
+ break;
+ }
+ ALOGD("%s channel map updated to [%d %d %d %d %d %d %d %d ]", __func__
+ , info->channel_map[0], info->channel_map[1], info->channel_map[2]
+ , info->channel_map[3], info->channel_map[4], info->channel_map[5]
+ , info->channel_map[6], info->channel_map[7]);
+}
+
+static void dump_edid_data(edid_audio_info *info)
+{
+
+ int i;
+ for (i = 0; i < info->audio_blocks && i < MAX_EDID_BLOCKS; i++) {
+ ALOGV("%s:FormatId:%d rate:%d bps:%d channels:%d", __func__,
+ info->audio_blocks_array[i].format_id,
+ info->audio_blocks_array[i].sampling_freq,
+ info->audio_blocks_array[i].bits_per_sample,
+ info->audio_blocks_array[i].channels);
+ }
+ ALOGV("%s:no of audio blocks:%d", __func__, info->audio_blocks);
+ ALOGV("%s:speaker allocation:[%x %x %x]", __func__,
+ info->speaker_allocation[0], info->speaker_allocation[1],
+ info->speaker_allocation[2]);
+ ALOGV("%s:channel map:[%x %x %x %x %x %x %x %x]", __func__,
+ info->channel_map[0], info->channel_map[1],
+ info->channel_map[2], info->channel_map[3],
+ info->channel_map[4], info->channel_map[5],
+ info->channel_map[6], info->channel_map[7]);
+ ALOGV("%s:channel allocation:%d", __func__, info->channel_allocation);
+ ALOGV("%s:[%d %d %d %d %d %d %d %d ]", __func__,
+ info->channel_map[0], info->channel_map[1],
+ info->channel_map[2], info->channel_map[3],
+ info->channel_map[4], info->channel_map[5],
+ info->channel_map[6], info->channel_map[7]);
+}
+
+bool edid_get_sink_caps(edid_audio_info* info, char *edid_data)
+{
+ unsigned char channels[MAX_EDID_BLOCKS];
+ unsigned char formats[MAX_EDID_BLOCKS];
+ unsigned char frequency[MAX_EDID_BLOCKS];
+ unsigned char bitrate[MAX_EDID_BLOCKS];
+ int i = 0;
+ int length, count_desc;
+
+ if (!info || !edid_data) {
+ ALOGE("No valid EDID");
+ return false;
+ }
+
+ length = (int) *edid_data++;
+ ALOGV("Total length is %d",length);
+
+ count_desc = length/MIN_AUDIO_DESC_LENGTH;
+
+ if (!count_desc) {
+ ALOGE("insufficient descriptors");
+ return false;
+ }
+
+ memset(info, 0, sizeof(edid_audio_info));
+
+ info->audio_blocks = count_desc-1;
+ if (info->audio_blocks > MAX_EDID_BLOCKS) {
+ info->audio_blocks = MAX_EDID_BLOCKS;
+ }
+
+ ALOGV("Total # of audio descriptors %d",count_desc);
+
+ for (i=0; i<info->audio_blocks; i++) {
+ // last block for speaker allocation;
+ channels [i] = (*edid_data & 0x7) + 1;
+ formats [i] = (*edid_data++) >> 3;
+ frequency[i] = *edid_data++;
+ bitrate [i] = *edid_data++;
+ }
+ info->speaker_allocation[0] = *edid_data++;
+ info->speaker_allocation[1] = *edid_data++;
+ info->speaker_allocation[2] = *edid_data++;
+
+ update_channel_map(info);
+ update_channel_allocation(info);
+ update_channel_map_lpass(info);
+
+ for (i=0; i<info->audio_blocks; i++) {
+ ALOGV("AUDIO DESC BLOCK # %d\n",i);
+
+ info->audio_blocks_array[i].channels = channels[i];
+ ALOGV("info->audio_blocks_array[i].channels %d\n",
+ info->audio_blocks_array[i].channels);
+
+ ALOGV("Format Byte %d\n", formats[i]);
+ info->audio_blocks_array[i].format_id = (edid_audio_format_id)formats[i];
+ ALOGV("info->audio_blocks_array[i].format_id %s",
+ edid_format_to_str(formats[i]));
+
+ ALOGV("Frequency Byte %d\n", frequency[i]);
+ info->audio_blocks_array[i].sampling_freq = get_edid_sf(frequency[i]);
+ ALOGV("info->audio_blocks_array[i].sampling_freq %d",
+ info->audio_blocks_array[i].sampling_freq);
+
+ ALOGV("BitsPerSample Byte %d\n", bitrate[i]);
+ info->audio_blocks_array[i].bits_per_sample =
+ get_edid_bps(bitrate[i],formats[i]);
+ ALOGV("info->audio_blocks_array[i].bits_per_sample %d",
+ info->audio_blocks_array[i].bits_per_sample);
+ }
+ dump_speaker_allocation(info);
+ dump_edid_data(info);
+ return true;
+}
diff --git a/hal/edid.h b/hal/edid.h
new file mode 100644
index 0000000..ec83ec8
--- /dev/null
+++ b/hal/edid.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2014, 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 EDID_H
+#define EDID_H
+
+/* HDMI EDID Information */
+#define BIT(nr) (1UL << (nr))
+#define MAX_EDID_BLOCKS 10
+#define MAX_SHORT_AUDIO_DESC_CNT 30
+#define MIN_AUDIO_DESC_LENGTH 3
+#define MIN_SPKR_ALLOCATION_DATA_LENGTH 3
+#define MAX_CHANNELS_SUPPORTED 8
+#define MAX_DISPLAY_DEVICES 3
+#define MAX_FRAME_BUFFER_NAME_SIZE 80
+#define MAX_CHAR_PER_INT 13
+
+#define PCM_CHANNEL_FL 1 /* Front left channel. */
+#define PCM_CHANNEL_FR 2 /* Front right channel. */
+#define PCM_CHANNEL_FC 3 /* Front center channel. */
+#define PCM_CHANNEL_LS 4 /* Left surround channel. */
+#define PCM_CHANNEL_RS 5 /* Right surround channel. */
+#define PCM_CHANNEL_LFE 6 /* Low frequency effect channel. */
+#define PCM_CHANNEL_CS 7 /* Center surround channel; Rear center channel. */
+#define PCM_CHANNEL_LB 8 /* Left back channel; Rear left channel. */
+#define PCM_CHANNEL_RB 9 /* Right back channel; Rear right channel. */
+#define PCM_CHANNEL_TS 10 /* Top surround channel. */
+#define PCM_CHANNEL_CVH 11 /* Center vertical height channel. */
+#define PCM_CHANNEL_MS 12 /* Mono surround channel. */
+#define PCM_CHANNEL_FLC 13 /* Front left of center. */
+#define PCM_CHANNEL_FRC 14 /* Front right of center. */
+#define PCM_CHANNEL_RLC 15 /* Rear left of center. */
+#define PCM_CHANNEL_RRC 16 /* Rear right of center. */
+
+#define MAX_HDMI_CHANNEL_CNT 8
+
+typedef enum edid_audio_format_id {
+ LPCM = 1,
+ AC3,
+ MPEG1,
+ MP3,
+ MPEG2_MULTI_CHANNEL,
+ AAC,
+ DTS,
+ ATRAC,
+ SACD,
+ DOLBY_DIGITAL_PLUS,
+ DTS_HD,
+ MAT,
+ DST,
+ WMA_PRO
+} edid_audio_format_id;
+
+typedef struct edid_audio_block_info {
+ edid_audio_format_id format_id;
+ int sampling_freq;
+ int bits_per_sample;
+ int channels;
+} edid_audio_block_info;
+
+typedef struct edid_audio_info {
+ int audio_blocks;
+ unsigned char speaker_allocation[MIN_SPKR_ALLOCATION_DATA_LENGTH];
+ edid_audio_block_info audio_blocks_array[MAX_EDID_BLOCKS];
+ char channel_map[MAX_CHANNELS_SUPPORTED];
+ int channel_allocation;
+} edid_audio_info;
+
+bool edid_get_sink_caps(edid_audio_info* info, char *edid_data);
+#endif /* EDID_H */
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index ca6d79b..201a170 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -121,7 +121,7 @@
/* Audio calibration related functions */
typedef void (*acdb_deallocate_t)();
-typedef int (*acdb_init_t)(char *, char *);
+typedef int (*acdb_init_t)(char *, char *, int);
typedef void (*acdb_send_audio_cal_t)(int, int, int, int);
typedef void (*acdb_send_voice_cal_t)(int, int);
typedef int (*acdb_reload_vocvoltable_t)(int);
@@ -915,7 +915,7 @@
char baseband[PROPERTY_VALUE_MAX];
char value[PROPERTY_VALUE_MAX];
struct platform_data *my_data = NULL;
- int retry_num = 0, snd_card_num = 0;
+ int retry_num = 0, snd_card_num = 0, key = 0;
const char *snd_card_name;
char mixer_xml_path[100],ffspEnable[PROPERTY_VALUE_MAX];
char *cvd_version = NULL;
@@ -1026,6 +1026,9 @@
acdb_device_table[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 131;
acdb_device_table[SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET] = 131;
}
+ property_get("audio.ds1.metainfo.key",value,"0");
+ key = atoi(value);
+
my_data->voice_feature_set = VOICE_FEATURE_SET_DEFAULT;
my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
if (my_data->acdb_handle == NULL) {
@@ -1076,7 +1079,7 @@
else
get_cvd_version(cvd_version, adev);
- my_data->acdb_init(snd_card_name, cvd_version);
+ my_data->acdb_init((char *)snd_card_name, cvd_version);
if (cvd_version)
free(cvd_version);
}
@@ -1094,6 +1097,9 @@
audio_extn_ssr_update_enabled();
audio_extn_spkr_prot_init(adev);
+ /* init dap hal */
+ audio_extn_dap_hal_init(adev->snd_card);
+
audio_extn_dolby_set_license(adev);
audio_hwdep_send_cal(my_data);
@@ -1110,6 +1116,7 @@
free(platform);
/* deinit usb */
audio_extn_usb_deinit();
+ audio_extn_dap_hal_deinit();
}
const char *platform_get_snd_device_name(snd_device_t snd_device)
@@ -1293,13 +1300,14 @@
return acdb_device_table[snd_device];
}
-int platform_set_snd_device_bit_width(snd_device_t snd_device, unsigned int bit_width)
+int platform_set_snd_device_bit_width(snd_device_t snd_device __unused,
+ unsigned int bit_width __unused)
{
ALOGE("%s: Not implemented", __func__);
return -ENOSYS;
}
-int platform_get_snd_device_bit_width(snd_device_t snd_device)
+int platform_get_snd_device_bit_width(snd_device_t snd_device __unused)
{
ALOGE("%s: Not implemented", __func__);
return -ENOSYS;
@@ -2633,3 +2641,34 @@
return -ENOSYS;
}
+int platform_get_edid_info(void *platform __unused)
+{
+ return -ENOSYS;
+}
+
+int platform_set_channel_map(void *platform __unused, int ch_count __unused,
+ char *ch_map __unused, int snd_id __unused)
+{
+ return -ENOSYS;
+}
+
+int platform_set_stream_channel_map(void *platform __unused,
+ audio_channel_mask_t channel_mask __unused,
+ int snd_id __unused)
+{
+ return -ENOSYS;
+}
+
+int platform_set_edid_channels_configuration(void *platform __unused,
+ int channels __unused)
+{
+ return 0;
+}
+
+void platform_cache_edid(void * platform __unused)
+{
+}
+
+void platform_invalidate_edid(void * platform __unused)
+{
+}
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index 941d39f..e73fb93 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -28,6 +28,7 @@
#include <audio_hw.h>
#include <platform_api.h>
#include "platform.h"
+#include "audio_extn.h"
#define LIB_ACDB_LOADER "libacdbloader.so"
#define LIB_CSD_CLIENT "libcsd-client.so"
@@ -421,13 +422,14 @@
return -ENOSYS;
}
-int platform_set_snd_device_bit_width(snd_device_t snd_device, unsigned int bit_width)
+int platform_set_snd_device_bit_width(snd_device_t snd_device __unused,
+ unsigned int bit_width __unused)
{
ALOGE("%s: Not implemented", __func__);
return -ENOSYS;
}
-int platform_get_snd_device_bit_width(snd_device_t snd_device)
+int platform_get_snd_device_bit_width(snd_device_t snd_device __unused)
{
ALOGE("%s: Not implemented", __func__);
return -ENOSYS;
@@ -1087,3 +1089,59 @@
{
return 0;
}
+
+int platform_get_edid_info(void *platform __unused)
+{
+ return -ENOSYS;
+}
+
+int platform_set_channel_map(void *platform __unused, int ch_count __unused,
+ char *ch_map __unused, int snd_id __unused)
+{
+ return -ENOSYS;
+}
+
+int platform_set_stream_channel_map(void *platform __unused,
+ audio_channel_mask_t channel_mask __unused,
+ int snd_id __unused)
+{
+ return -ENOSYS;
+}
+
+int platform_set_edid_channels_configuration(void *platform __unused,
+ int channels __unused)
+{
+ return 0;
+}
+
+unsigned char platform_map_to_edid_format(int format __unused)
+{
+ return 0;
+}
+
+bool platform_is_edid_supported_format(void *platform __unused,
+ int format __unused)
+{
+ return false;
+}
+
+void platform_cache_edid(void * platform __unused)
+{
+
+}
+
+void platform_invalidate_edid(void * platform __unused)
+{
+
+}
+
+int platform_set_hdmi_config(struct stream_out *out __unused)
+{
+ return 0;
+}
+
+int platform_set_device_params(struct stream_out *out __unused,
+ int param __unused, int value __unused)
+{
+ return 0;
+}
diff --git a/hal/msm8960/platform.h b/hal/msm8960/platform.h
index 950ea84..4b4d14e 100644
--- a/hal/msm8960/platform.h
+++ b/hal/msm8960/platform.h
@@ -145,4 +145,6 @@
#define AFE_PROXY_PLAYBACK_PCM_DEVICE 7
#define AFE_PROXY_RECORD_PCM_DEVICE 8
+#define DEVICE_NAME_MAX_SIZE 128
+
#endif // QCOM_AUDIO_PLATFORM_H
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 6887194..1c19a61 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -20,6 +20,12 @@
#define LOG_TAG "msm8974_platform"
/*#define LOG_NDEBUG 0*/
#define LOG_NDDEBUG 0
+/*#define VERY_VERY_VERBOSE_LOGGING*/
+#ifdef VERY_VERY_VERBOSE_LOGGING
+#define ALOGVV ALOGV
+#else
+#define ALOGVV(a...) do { } while(0)
+#endif
#include <stdlib.h>
#include <dlfcn.h>
@@ -33,6 +39,7 @@
#include "platform.h"
#include "audio_extn.h"
#include "voice_extn.h"
+#include "edid.h"
#include "sound/compress_params.h"
#include "sound/msmcal-hwdep.h"
@@ -56,6 +63,8 @@
/* Used in calculating fragment size for pcm offload */
#define PCM_OFFLOAD_BUFFER_DURATION_FOR_AV 1000 /* 1 sec */
#define PCM_OFFLOAD_BUFFER_DURATION_FOR_AV_STREAMING 80 /* 80 millisecs */
+#define PCM_OFFLOAD_BUFFER_DURATION_FOR_SMALL_BUFFERS 20 /* 20 millisecs */
+#define PCM_OFFLOAD_BUFFER_DURATION_MAX 1200 /* 1200 millisecs */
/* MAX PCM fragment size cannot be increased further due
* to flinger's cblk size of 1mb,and it has to be a multiple of
@@ -64,6 +73,12 @@
#define MAX_PCM_OFFLOAD_FRAGMENT_SIZE (240 * 1024)
#define MIN_PCM_OFFLOAD_FRAGMENT_SIZE (4 * 1024)
+/*
+ * Offload buffer size for compress passthrough
+ */
+#define MIN_COMPRESS_PASSTHROUGH_FRAGMENT_SIZE (2 * 1024)
+#define MAX_COMPRESS_PASSTHROUGH_FRAGMENT_SIZE (8 * 1024)
+
#define ALIGN( num, to ) (((num) + (to-1)) & (~(to-1)))
/*
* This file will have a maximum of 38 bytes:
@@ -141,7 +156,7 @@
/* Audio calibration related functions */
typedef void (*acdb_deallocate_t)();
-typedef int (*acdb_init_t)(const char *, char *);
+typedef int (*acdb_init_t)(const char *, char *, int);
typedef void (*acdb_send_audio_cal_t)(int, int, int , int);
typedef void (*acdb_send_voice_cal_t)(int, int);
typedef int (*acdb_reload_vocvoltable_t)(int);
@@ -181,6 +196,8 @@
void *hw_info;
struct csd_data *csd;
+ void *edid_info;
+ bool edid_valid;
};
static int pcm_device_table[AUDIO_USECASE_MAX][2] = {
@@ -340,6 +357,10 @@
[SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE] = "speaker-dmic-broadside",
[SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE] = "speaker-dmic-broadside",
[SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE] = "speaker-dmic-broadside",
+ [SND_DEVICE_IN_HANDSET_QMIC] = "quad-mic",
+ [SND_DEVICE_IN_SPEAKER_QMIC_AEC] = "quad-mic",
+ [SND_DEVICE_IN_SPEAKER_QMIC_NS] = "quad-mic",
+ [SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS] = "quad-mic",
};
// Platform specific backend bit width table
@@ -432,6 +453,10 @@
[SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE] = 119,
[SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE] = 121,
[SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE] = 120,
+ [SND_DEVICE_IN_HANDSET_QMIC] = 125,
+ [SND_DEVICE_IN_SPEAKER_QMIC_AEC] = 126,
+ [SND_DEVICE_IN_SPEAKER_QMIC_NS] = 127,
+ [SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS] = 129,
};
struct name_to_index {
@@ -523,6 +548,10 @@
{TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE)},
{TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE)},
{TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE)},
+ {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_QMIC)},
+ {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_AEC)},
+ {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_NS)},
+ {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS)},
};
static char * backend_table[SND_DEVICE_MAX] = {0};
@@ -624,19 +653,18 @@
struct platform_data *my_data = (struct platform_data *)platform;
struct audio_device *adev = my_data->adev;
- if (enable) {
- my_data->ec_ref_enabled = enable;
- audio_route_apply_and_update_path(adev->audio_route, "echo-reference");
- } else {
- if (my_data->ec_ref_enabled) {
- audio_route_reset_and_update_path(adev->audio_route, "echo-reference");
- my_data->ec_ref_enabled = enable;
- } else {
- ALOGV("EC Reference is already disabled: %d", my_data->ec_ref_enabled);
- }
+ if (my_data->ec_ref_enabled) {
+ my_data->ec_ref_enabled = false;
+ ALOGV("%s: disabling echo-reference", __func__);
+ audio_route_reset_and_update_path(adev->audio_route, "echo-reference");
}
- ALOGV("Setting EC Reference: %d", enable);
+ if (enable) {
+ my_data->ec_ref_enabled = true;
+ ALOGD("%s: enabling echo-reference", __func__);
+ audio_route_apply_and_update_path(adev->audio_route, "echo-reference");
+ }
+
}
static struct csd_data *open_csd_client(bool i2s_ext_modem)
@@ -959,7 +987,7 @@
char baseband[PROPERTY_VALUE_MAX];
char value[PROPERTY_VALUE_MAX];
struct platform_data *my_data = NULL;
- int retry_num = 0, snd_card_num = 0;
+ int retry_num = 0, snd_card_num = 0, key = 0;
const char *snd_card_name;
char *cvd_version = NULL;
@@ -1036,6 +1064,7 @@
my_data->fluence_mode = FLUENCE_ENDFIRE;
my_data->slowtalk = false;
my_data->hd_voice = false;
+ my_data->edid_info = NULL;
property_get("ro.qc.sdk.audio.fluencetype", my_data->fluence_cap, "");
if (!strncmp("fluencepro", my_data->fluence_cap, sizeof("fluencepro"))) {
@@ -1072,6 +1101,8 @@
my_data->fluence_mode = FLUENCE_BROADSIDE;
}
}
+ property_get("audio.ds1.metainfo.key",value,"0");
+ key = atoi(value);
my_data->voice_feature_set = VOICE_FEATURE_SET_DEFAULT;
my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
@@ -1135,7 +1166,7 @@
else
get_cvd_version(cvd_version, adev);
- my_data->acdb_init(snd_card_name, cvd_version);
+ my_data->acdb_init(snd_card_name, cvd_version, key);
if (cvd_version)
free(cvd_version);
}
@@ -1181,6 +1212,7 @@
/* init audio device arbitration */
audio_extn_dev_arbi_init();
+ my_data->edid_info = NULL;
return my_data;
}
@@ -1188,6 +1220,11 @@
{
struct platform_data *my_data = (struct platform_data *)platform;
+ if (my_data->edid_info) {
+ free(my_data->edid_info);
+ my_data->edid_info = NULL;
+ }
+
hw_info_deinit(my_data->hw_info);
close_csd_client(my_data->csd);
@@ -1202,6 +1239,11 @@
/* deinit audio device arbitration */
audio_extn_dev_arbi_deinit();
+ if (my_data->edid_info) {
+ free(my_data->edid_info);
+ my_data->edid_info = NULL;
+ }
+
free(platform);
/* deinit usb */
audio_extn_usb_deinit();
@@ -1990,12 +2032,15 @@
if (adev->active_input->enable_aec &&
adev->active_input->enable_ns) {
if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
- if (my_data->fluence_type & FLUENCE_DUAL_MIC &&
- my_data->fluence_in_spkr_mode) {
- if (my_data->fluence_mode == FLUENCE_BROADSIDE)
- snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE;
- else
- snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
+ if (my_data->fluence_in_spkr_mode) {
+ if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
+ snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS;
+ } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+ if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE;
+ else
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
+ }
} else
snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
} else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
@@ -2009,12 +2054,15 @@
platform_set_echo_reference(adev->platform, true);
} else if (adev->active_input->enable_aec) {
if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
- if (my_data->fluence_type & FLUENCE_DUAL_MIC &&
- my_data->fluence_in_spkr_mode) {
- if (my_data->fluence_mode == FLUENCE_BROADSIDE)
- snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE;
- else
- snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC;
+ if (my_data->fluence_in_spkr_mode) {
+ if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
+ snd_device = SND_DEVICE_IN_SPEAKER_QMIC_AEC;
+ } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+ if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE;
+ else
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC;
+ }
} else
snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
} else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
@@ -2028,12 +2076,15 @@
platform_set_echo_reference(adev->platform, true);
} else if (adev->active_input->enable_ns) {
if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
- if (my_data->fluence_type & FLUENCE_DUAL_MIC &&
- my_data->fluence_in_spkr_mode) {
- if (my_data->fluence_mode == FLUENCE_BROADSIDE)
- snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE;
- else
- snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS;
+ if (my_data->fluence_in_spkr_mode) {
+ if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
+ snd_device = SND_DEVICE_IN_SPEAKER_QMIC_NS;
+ } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+ if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE;
+ else
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS;
+ }
} else
snd_device = SND_DEVICE_IN_SPEAKER_MIC_NS;
} else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
@@ -2051,10 +2102,14 @@
} else if (source == AUDIO_SOURCE_MIC) {
if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC &&
channel_count == 1 ) {
- if(my_data->fluence_type & FLUENCE_DUAL_MIC &&
- my_data->fluence_in_audio_rec) {
- snd_device = SND_DEVICE_IN_HANDSET_DMIC;
- platform_set_echo_reference(adev->platform, true);
+ if(my_data->fluence_in_audio_rec) {
+ if(my_data->fluence_type & FLUENCE_QUAD_MIC) {
+ snd_device = SND_DEVICE_IN_HANDSET_QMIC;
+ platform_set_echo_reference(adev->platform, true);
+ } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
+ snd_device = SND_DEVICE_IN_HANDSET_DMIC;
+ platform_set_echo_reference(adev->platform, true);
+ }
}
}
} else if (source == AUDIO_SOURCE_FM_RX ||
@@ -2184,56 +2239,28 @@
int platform_edid_get_max_channels(void *platform)
{
+ int channel_count;
+ int max_channels = 2;
+ int i = 0, ret = 0;
struct platform_data *my_data = (struct platform_data *)platform;
struct audio_device *adev = my_data->adev;
- char block[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE];
- char *sad = block;
- int num_audio_blocks;
- int channel_count;
- int max_channels = 0;
- int i, ret, count;
+ edid_audio_info *info = NULL;
+ ret = platform_get_edid_info(platform);
+ info = (edid_audio_info *)my_data->edid_info;
- struct mixer_ctl *ctl;
-
- ctl = mixer_get_ctl_by_name(adev->mixer, AUDIO_DATA_BLOCK_MIXER_CTL);
- if (!ctl) {
- ALOGE("%s: Could not get ctl for mixer cmd - %s",
- __func__, AUDIO_DATA_BLOCK_MIXER_CTL);
- return 0;
- }
-
- mixer_ctl_update(ctl);
-
- count = mixer_ctl_get_num_values(ctl);
-
- /* Read SAD blocks, clamping the maximum size for safety */
- if (count > (int)sizeof(block))
- count = (int)sizeof(block);
-
- ret = mixer_ctl_get_array(ctl, block, count);
- if (ret != 0) {
- ALOGE("%s: mixer_ctl_get_array() failed to get EDID info", __func__);
- return 0;
- }
-
- /* Calculate the number of SAD blocks */
- num_audio_blocks = count / SAD_BLOCK_SIZE;
-
- for (i = 0; i < num_audio_blocks; i++) {
- /* Only consider LPCM blocks */
- if ((sad[0] >> 3) != EDID_FORMAT_LPCM) {
- sad += 3;
- continue;
+ if(ret == 0 && info != NULL) {
+ for (i = 0; i < info->audio_blocks && i < MAX_EDID_BLOCKS; i++) {
+ ALOGV("%s:format %d channel %d", __func__,
+ info->audio_blocks_array[i].format_id,
+ info->audio_blocks_array[i].channels);
+ if (info->audio_blocks_array[i].format_id == LPCM) {
+ channel_count = info->audio_blocks_array[i].channels;
+ if (channel_count > max_channels) {
+ max_channels = channel_count;
+ }
+ }
}
-
- channel_count = (sad[0] & 0x7) + 1;
- if (channel_count > max_channels)
- max_channels = channel_count;
-
- /* Advance to next block */
- sad += 3;
}
-
return max_channels;
}
@@ -2873,44 +2900,42 @@
uint32_t platform_get_pcm_offload_buffer_size(audio_offload_info_t* info)
{
- uint32_t fragment_size = MIN_PCM_OFFLOAD_FRAGMENT_SIZE;
+ uint32_t fragment_size = 0;
uint32_t bits_per_sample = 16;
+ uint32_t pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION_FOR_SMALL_BUFFERS;
if (info->format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD) {
bits_per_sample = 32;
}
- if (!info->has_video) {
- fragment_size = MAX_PCM_OFFLOAD_FRAGMENT_SIZE;
-
- } else if (info->has_video && info->is_streaming) {
- fragment_size = (PCM_OFFLOAD_BUFFER_DURATION_FOR_AV_STREAMING
- * info->sample_rate
- * (bits_per_sample >> 3)
- * popcount(info->channel_mask))/1000;
-
- } else if (info->has_video) {
- fragment_size = (PCM_OFFLOAD_BUFFER_DURATION_FOR_AV
- * info->sample_rate
- * (bits_per_sample >> 3)
- * popcount(info->channel_mask))/1000;
+ if (info->use_small_bufs) {
+ pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION_FOR_SMALL_BUFFERS;
+ } else {
+ if (!info->has_video) {
+ pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION_MAX;
+ } else if (info->has_video && info->is_streaming) {
+ pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION_FOR_AV_STREAMING;
+ } else if (info->has_video) {
+ pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION_FOR_AV;
+ }
}
- char value[PROPERTY_VALUE_MAX] = {0};
- if((property_get("audio.offload.pcm.buffer.size", value, "")) &&
- atoi(value)) {
- fragment_size = atoi(value) * 1024;
- ALOGV("Using buffer size from sys prop %d", fragment_size);
- }
+ //duration is set to 20 ms worth of stereo data at 48Khz
+ //with 16 bit per sample, modify this when the channel
+ //configuration is different
+ fragment_size = (pcm_offload_time
+ * info->sample_rate
+ * (bits_per_sample >> 3)
+ * popcount(info->channel_mask))/1000;
- fragment_size = ALIGN( fragment_size, 1024);
+ fragment_size = ALIGN (fragment_size, 1024);
if(fragment_size < MIN_PCM_OFFLOAD_FRAGMENT_SIZE)
fragment_size = MIN_PCM_OFFLOAD_FRAGMENT_SIZE;
else if(fragment_size > MAX_PCM_OFFLOAD_FRAGMENT_SIZE)
fragment_size = MAX_PCM_OFFLOAD_FRAGMENT_SIZE;
- ALOGV("%s: fragment_size %d", __func__, fragment_size);
+ ALOGI("PCM offload Fragment size to %d bytes", fragment_size);
return fragment_size;
}
@@ -3125,3 +3150,495 @@
*device_to_be_id = msm_device_to_be_id;
*length = msm_be_id_array_len;
}
+
+int platform_set_stream_channel_map(void *platform, audio_channel_mask_t channel_mask, int snd_id)
+{
+ int ret = 0;
+ int channels = audio_channel_count_from_out_mask(channel_mask);
+
+ char channel_map[8];
+ memset(channel_map, 0, sizeof(channel_map));
+ /* Following are all most common standard WAV channel layouts
+ overridden by channel mask if its allowed and different */
+ switch (channels) {
+ case 1:
+ /* AUDIO_CHANNEL_OUT_MONO */
+ channel_map[0] = PCM_CHANNEL_FC;
+ break;
+ case 2:
+ /* AUDIO_CHANNEL_OUT_STEREO */
+ channel_map[0] = PCM_CHANNEL_FL;
+ channel_map[1] = PCM_CHANNEL_FR;
+ break;
+ case 3:
+ /* AUDIO_CHANNEL_OUT_2POINT1 */
+ channel_map[0] = PCM_CHANNEL_FL;
+ channel_map[1] = PCM_CHANNEL_FR;
+ channel_map[2] = PCM_CHANNEL_FC;
+ break;
+ case 4:
+ /* AUDIO_CHANNEL_OUT_QUAD_SIDE */
+ channel_map[0] = PCM_CHANNEL_FL;
+ channel_map[1] = PCM_CHANNEL_FR;
+ channel_map[2] = PCM_CHANNEL_LS;
+ channel_map[3] = PCM_CHANNEL_RS;
+ if (channel_mask == AUDIO_CHANNEL_OUT_QUAD_BACK)
+ {
+ channel_map[2] = PCM_CHANNEL_LB;
+ channel_map[3] = PCM_CHANNEL_RB;
+ }
+ if (channel_mask == AUDIO_CHANNEL_OUT_SURROUND)
+ {
+ channel_map[2] = PCM_CHANNEL_FC;
+ channel_map[3] = PCM_CHANNEL_CS;
+ }
+ break;
+ case 5:
+ /* AUDIO_CHANNEL_OUT_PENTA */
+ channel_map[0] = PCM_CHANNEL_FL;
+ channel_map[1] = PCM_CHANNEL_FR;
+ channel_map[2] = PCM_CHANNEL_FC;
+ channel_map[3] = PCM_CHANNEL_LB;
+ channel_map[4] = PCM_CHANNEL_RB;
+ break;
+ case 6:
+ /* AUDIO_CHANNEL_OUT_5POINT1 */
+ channel_map[0] = PCM_CHANNEL_FL;
+ channel_map[1] = PCM_CHANNEL_FR;
+ channel_map[2] = PCM_CHANNEL_FC;
+ channel_map[3] = PCM_CHANNEL_LFE;
+ channel_map[4] = PCM_CHANNEL_LB;
+ channel_map[5] = PCM_CHANNEL_RB;
+ if (channel_mask == AUDIO_CHANNEL_OUT_5POINT1_SIDE)
+ {
+ channel_map[4] = PCM_CHANNEL_LS;
+ channel_map[5] = PCM_CHANNEL_RS;
+ }
+ break;
+ case 7:
+ /* AUDIO_CHANNEL_OUT_6POINT1 */
+ channel_map[0] = PCM_CHANNEL_FL;
+ channel_map[1] = PCM_CHANNEL_FR;
+ channel_map[2] = PCM_CHANNEL_FC;
+ channel_map[3] = PCM_CHANNEL_LFE;
+ channel_map[4] = PCM_CHANNEL_LB;
+ channel_map[5] = PCM_CHANNEL_RB;
+ channel_map[6] = PCM_CHANNEL_CS;
+ break;
+ case 8:
+ /* AUDIO_CHANNEL_OUT_7POINT1 */
+ channel_map[0] = PCM_CHANNEL_FL;
+ channel_map[1] = PCM_CHANNEL_FR;
+ channel_map[2] = PCM_CHANNEL_FC;
+ channel_map[3] = PCM_CHANNEL_LFE;
+ channel_map[4] = PCM_CHANNEL_LB;
+ channel_map[5] = PCM_CHANNEL_RB;
+ channel_map[6] = PCM_CHANNEL_LS;
+ channel_map[7] = PCM_CHANNEL_RS;
+ break;
+ default:
+ ALOGE("unsupported channels %d for setting channel map", channels);
+ return -1;
+ }
+ ret = platform_set_channel_map(platform, channels, channel_map, snd_id);
+ return ret;
+}
+
+int platform_get_edid_info(void *platform)
+{
+ struct platform_data *my_data = (struct platform_data *)platform;
+ struct audio_device *adev = my_data->adev;
+ char block[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE];
+ char *sad = block;
+ int num_audio_blocks;
+ int channel_count = 2;
+ int i, ret, count;
+
+ struct mixer_ctl *ctl;
+ char edid_data[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE + 1] = {0};
+ edid_audio_info *info;
+
+ if (my_data->edid_valid) {
+ /* use cached edid */
+ return 0;
+ }
+
+ if (my_data->edid_info == NULL) {
+ my_data->edid_info =
+ (struct edid_audio_info *)calloc(1, sizeof(struct edid_audio_info));
+ }
+
+ info = my_data->edid_info;
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, AUDIO_DATA_BLOCK_MIXER_CTL);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",
+ __func__, AUDIO_DATA_BLOCK_MIXER_CTL);
+ goto fail;
+ }
+
+ mixer_ctl_update(ctl);
+
+ count = mixer_ctl_get_num_values(ctl);
+
+ /* Read SAD blocks, clamping the maximum size for safety */
+ if (count > (int)sizeof(block))
+ count = (int)sizeof(block);
+
+ ret = mixer_ctl_get_array(ctl, block, count);
+ if (ret != 0) {
+ ALOGE("%s: mixer_ctl_get_array() failed to get EDID info", __func__);
+ goto fail;
+ }
+ edid_data[0] = count;
+ memcpy(&edid_data[1], block, count);
+
+ if (!edid_get_sink_caps(info, edid_data)) {
+ ALOGE("%s: Failed to get HDMI sink capabilities", __func__);
+ goto fail;
+ }
+ my_data->edid_valid = true;
+ return 0;
+fail:
+ if (my_data->edid_info) {
+ free(my_data->edid_info);
+ my_data->edid_info = NULL;
+ my_data->edid_valid = false;
+ }
+ ALOGE("%s: return -EINVAL", __func__);
+ return -EINVAL;
+}
+
+
+int platform_set_channel_allocation(void *platform, int channel_alloc)
+{
+ struct mixer_ctl *ctl;
+ const char *mixer_ctl_name = "HDMI RX CA";
+ int ret;
+ struct platform_data *my_data = (struct platform_data *)platform;
+ struct audio_device *adev = my_data->adev;
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",
+ __func__, mixer_ctl_name);
+ ret = EINVAL;
+ }
+ ALOGD(":%s channel allocation = 0x%x", __func__, channel_alloc);
+ ret = mixer_ctl_set_value(ctl, 0, channel_alloc);
+
+ if (ret < 0) {
+ ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
+ }
+
+ return ret;
+}
+
+int platform_set_channel_map(void *platform, int ch_count, char *ch_map, int snd_id)
+{
+ struct mixer_ctl *ctl;
+ char mixer_ctl_name[44]; // max length of name is 44 as defined
+ int ret;
+ unsigned int i;
+ int set_values[8] = {0};
+ char device_num[13]; // device number up to 2 digit
+ struct platform_data *my_data = (struct platform_data *)platform;
+ struct audio_device *adev = my_data->adev;
+ ALOGV("%s channel_count:%d",__func__, ch_count);
+ if (NULL == ch_map) {
+ ALOGE("%s: Invalid channel mapping used", __func__);
+ return -EINVAL;
+ }
+ strlcpy(mixer_ctl_name, "Playback Channel Map", sizeof(mixer_ctl_name));
+ if (snd_id >= 0) {
+ snprintf(device_num, sizeof(device_num), "%d", snd_id);
+ strncat(mixer_ctl_name, device_num, 13);
+ }
+
+ ALOGD("%s mixer_ctl_name:%s", __func__, mixer_ctl_name);
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",
+ __func__, mixer_ctl_name);
+ return -EINVAL;
+ }
+ for (i = 0; i< ARRAY_SIZE(set_values); i++) {
+ set_values[i] = ch_map[i];
+ }
+
+ ALOGD("%s: set mapping(%d %d %d %d %d %d %d %d) for channel:%d", __func__,
+ set_values[0], set_values[1], set_values[2], set_values[3], set_values[4],
+ set_values[5], set_values[6], set_values[7], ch_count);
+
+ ret = mixer_ctl_set_array(ctl, set_values, ch_count);
+ if (ret < 0) {
+ ALOGE("%s: Could not set ctl, error:%d ch_count:%d",
+ __func__, ret, ch_count);
+ }
+ return ret;
+}
+
+unsigned char platform_map_to_edid_format(int audio_format)
+{
+ unsigned char format;
+ switch (audio_format & AUDIO_FORMAT_MAIN_MASK) {
+ case AUDIO_FORMAT_AC3:
+ ALOGV("%s: AC3", __func__);
+ format = AC3;
+ break;
+ case AUDIO_FORMAT_AAC:
+ ALOGV("%s:AAC", __func__);
+ format = AAC;
+ break;
+ case AUDIO_FORMAT_E_AC3:
+ ALOGV("%s:E_AC3", __func__);
+ format = DOLBY_DIGITAL_PLUS;
+ break;
+ case AUDIO_FORMAT_PCM_16_BIT:
+ case AUDIO_FORMAT_PCM_16_BIT_OFFLOAD:
+ case AUDIO_FORMAT_PCM_24_BIT_OFFLOAD:
+ default:
+ ALOGV("%s:PCM", __func__);
+ format = LPCM;
+ break;
+ }
+ return format;
+}
+
+uint32_t platform_get_compress_passthrough_buffer_size(
+ audio_offload_info_t* info)
+{
+ uint32_t fragment_size = MIN_COMPRESS_PASSTHROUGH_FRAGMENT_SIZE;
+ if (!info->has_video)
+ fragment_size = MIN_COMPRESS_PASSTHROUGH_FRAGMENT_SIZE;
+
+ return fragment_size;
+}
+
+void platform_reset_edid_info(void *platform) {
+
+ ALOGV("%s:", __func__);
+ struct platform_data *my_data = (struct platform_data *)platform;
+ if (my_data->edid_info) {
+ ALOGV("%s :free edid", __func__);
+ free(my_data->edid_info);
+ my_data->edid_info = NULL;
+ }
+}
+
+bool platform_is_edid_supported_format(void *platform, int format)
+{
+ struct platform_data *my_data = (struct platform_data *)platform;
+ struct audio_device *adev = my_data->adev;
+ edid_audio_info *info = NULL;
+ int num_audio_blocks;
+ int i, ret, count;
+ unsigned char format_id = platform_map_to_edid_format(format);
+
+ ret = platform_get_edid_info(platform);
+ info = (edid_audio_info *)my_data->edid_info;
+ if (ret == 0 && info != NULL) {
+ for (i = 0; i < info->audio_blocks && i < MAX_EDID_BLOCKS; i++) {
+ /*
+ * To check
+ * is there any special for CONFIG_HDMI_PASSTHROUGH_CONVERT
+ * & DOLBY_DIGITAL_PLUS
+ */
+ if (info->audio_blocks_array[i].format_id == format_id) {
+ ALOGV("%s:platform_is_edid_supported_format true %x",
+ __func__, format);
+ return true;
+ }
+ }
+ }
+ ALOGV("%s:platform_is_edid_supported_format false %x",
+ __func__, format);
+ return false;
+}
+
+int platform_set_edid_channels_configuration(void *platform, int channels) {
+
+ struct platform_data *my_data = (struct platform_data *)platform;
+ struct audio_device *adev = my_data->adev;
+ edid_audio_info *info = NULL;
+ int num_audio_blocks;
+ int channel_count = 2;
+ int i, ret, count;
+ char default_channelMap[MAX_CHANNELS_SUPPORTED] = {0};
+
+ ret = platform_get_edid_info(platform);
+ info = (edid_audio_info *)my_data->edid_info;
+ if(ret == 0 && info != NULL) {
+ if (channels > 2) {
+
+ ALOGV("%s:able to get HDMI sink capabilities multi channel playback",
+ __func__);
+ for (i = 0; i < info->audio_blocks && i < MAX_EDID_BLOCKS; i++) {
+ if (info->audio_blocks_array[i].format_id == LPCM &&
+ info->audio_blocks_array[i].channels > channel_count &&
+ info->audio_blocks_array[i].channels <= MAX_HDMI_CHANNEL_CNT) {
+ channel_count = info->audio_blocks_array[i].channels;
+ }
+ }
+ ALOGVV("%s:channel_count:%d", __func__, channel_count);
+ /*
+ * Channel map is set for supported hdmi max channel count even
+ * though the input channel count set on adm is less than or equal to
+ * max supported channel count
+ */
+ platform_set_channel_map(platform, channel_count, info->channel_map, -1);
+ platform_set_channel_allocation(platform, info->channel_allocation);
+ } else {
+ default_channelMap[0] = PCM_CHANNEL_FL;
+ default_channelMap[1] = PCM_CHANNEL_FR;
+ platform_set_channel_map(platform,2,default_channelMap,-1);
+ platform_set_channel_allocation(platform,0);
+ }
+ }
+
+ return 0;
+}
+
+void platform_cache_edid(void * platform)
+{
+ platform_get_edid_info(platform);
+}
+
+void platform_invalidate_edid(void * platform)
+{
+ struct platform_data *my_data = (struct platform_data *)platform;
+ my_data->edid_valid = false;
+ if (my_data->edid_info) {
+ memset(my_data->edid_info, 0, sizeof(struct edid_audio_info));
+ }
+}
+
+int platform_set_mixer_control(struct stream_out *out, const char * mixer_ctl_name,
+ const char *mixer_val)
+{
+ struct audio_device *adev = out->dev;
+ struct mixer_ctl *ctl = NULL;
+ ALOGD("setting mixer ctl %s with value %s", mixer_ctl_name, mixer_val);
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: could not get ctl for mixer cmd - %s",
+ __func__, mixer_ctl_name);
+ return -EINVAL;
+ }
+
+ return mixer_ctl_set_enum_by_string(ctl, mixer_val);
+}
+
+int platform_set_hdmi_config(struct stream_out *out)
+{
+ struct listnode *node;
+ struct audio_usecase *usecase;
+ struct audio_device *adev = out->dev;
+ const char *hdmi_format_ctrl = "HDMI RX Format";
+ const char *hdmi_rate_ctrl = "HDMI_RX SampleRate";
+ int sample_rate = out->sample_rate;
+ /*TODO: Add rules and check if this needs to be done.*/
+ if((is_offload_usecase(out->usecase)) &&
+ (out->compr_config.codec->compr_passthr == PASSTHROUGH ||
+ out->compr_config.codec->compr_passthr == PASSTHROUGH_CONVERT)) {
+ /* TODO: can we add mixer control for channels here avoid setting */
+ if ((out->format == AUDIO_FORMAT_E_AC3 ||
+ out->format == AUDIO_FORMAT_E_AC3_JOC) &&
+ (out->compr_config.codec->compr_passthr == PASSTHROUGH))
+ sample_rate = out->sample_rate * 4;
+ ALOGD("%s:HDMI compress format and samplerate %d, sample_rate %d",
+ __func__, out->sample_rate, sample_rate);
+ platform_set_mixer_control(out, hdmi_format_ctrl, "Compr");
+ switch (sample_rate) {
+ case 32000:
+ platform_set_mixer_control(out, hdmi_rate_ctrl, "KHZ_32");
+ break;
+ case 44100:
+ platform_set_mixer_control(out, hdmi_rate_ctrl, "KHZ_44_1");
+ break;
+ case 96000:
+ platform_set_mixer_control(out, hdmi_rate_ctrl, "KHZ_96");
+ break;
+ case 176400:
+ platform_set_mixer_control(out, hdmi_rate_ctrl, "KHZ_176_4");
+ break;
+ case 192000:
+ platform_set_mixer_control(out, hdmi_rate_ctrl, "KHZ_192");
+ break;
+ case 128000:
+ if (out->format != AUDIO_FORMAT_E_AC3) {
+ platform_set_mixer_control(out, hdmi_rate_ctrl, "KHZ_128");
+ break;
+ } else
+ ALOGW("Unsupported sample rate for E_AC3 32K");
+ default:
+ case 48000:
+ platform_set_mixer_control(out, hdmi_rate_ctrl, "KHZ_48");
+ break;
+ }
+ } else {
+ ALOGD("%s: HDMI pcm and samplerate %d", __func__,
+ out->sample_rate);
+ platform_set_mixer_control(out, hdmi_format_ctrl, "LPCM");
+ platform_set_mixer_control(out, hdmi_rate_ctrl, "KHZ_48");
+ }
+
+ /*
+ * Deroute all the playback streams routed to HDMI so that
+ * the back end is deactivated. Note that backend will not
+ * be deactivated if any one stream is connected to it.
+ */
+ list_for_each(node, &adev->usecase_list) {
+ usecase = node_to_item(node, struct audio_usecase, list);
+ ALOGV("%s:disable: usecase type %d, devices 0x%x", __func__,
+ usecase->type, usecase->devices);
+ if (usecase->type == PCM_PLAYBACK &&
+ usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
+ disable_audio_route(adev, usecase);
+ }
+ }
+
+ /*
+ * Enable all the streams disabled above. Now the HDMI backend
+ * will be activated with new channel configuration
+ */
+ list_for_each(node, &adev->usecase_list) {
+ usecase = node_to_item(node, struct audio_usecase, list);
+ ALOGV("%s:enable: usecase type %d, devices 0x%x", __func__,
+ usecase->type, usecase->devices);
+ if (usecase->type == PCM_PLAYBACK &&
+ usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
+ enable_audio_route(adev, usecase);
+ }
+ }
+
+ return 0;
+}
+
+int platform_set_device_params(struct stream_out *out, int param, int value)
+{
+ struct audio_device *adev = out->dev;
+ struct mixer_ctl *ctl;
+ char *mixer_ctl_name = "Device PP Params";
+ int ret = 0;
+ uint32_t set_values[] = {0,0};
+
+ set_values[0] = param;
+ set_values[1] = value;
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",
+ __func__, mixer_ctl_name);
+ ret = -EINVAL;
+ goto end;
+ }
+
+ ALOGV("%s: Setting device pp params param: %d, value %d mixer ctrl:%s",
+ __func__,param, value, mixer_ctl_name);
+ mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
+
+end:
+ return ret;
+}
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 615912e..c7d7f0e 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -141,6 +141,10 @@
SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE,
SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE,
SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE,
+ SND_DEVICE_IN_HANDSET_QMIC,
+ SND_DEVICE_IN_SPEAKER_QMIC_AEC,
+ SND_DEVICE_IN_SPEAKER_QMIC_NS,
+ SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS,
SND_DEVICE_IN_END,
SND_DEVICE_MAX = SND_DEVICE_IN_END,
@@ -344,4 +348,16 @@
get_sample_rate_t get_sample_rate;
};
+/* HDMI Passthrough defines */
+enum {
+ LEGACY_PCM = 0,
+ PASSTHROUGH,
+ PASSTHROUGH_CONVERT
+};
+/*
+ * ID for setting mute and lateny on the device side
+ * through Device PP Params mixer control.
+ */
+#define DEVICE_PARAM_MUTE_ID 0
+#define DEVICE_PARAM_LATENCY_ID 1
#endif // QCOM_AUDIO_PLATFORM_H
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 368677b..ab2cc9d 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -89,6 +89,7 @@
struct audio_offload_info_t;
uint32_t platform_get_compress_offload_buffer_size(audio_offload_info_t* info);
uint32_t platform_get_pcm_offload_buffer_size(audio_offload_info_t* info);
+uint32_t platform_get_compress_passthrough_buffer_size(audio_offload_info_t* info);
bool platform_check_and_set_codec_backend_cfg(struct audio_device* adev, struct audio_usecase *usecase);
int platform_get_usecase_index(const char * usecase);
@@ -96,4 +97,16 @@
void platform_set_echo_reference(void *platform, bool enable);
void platform_get_device_to_be_id_map(int **be_id_map, int *length);
+int platform_set_channel_allocation(void *platform, int channel_alloc);
+int platform_get_edid_info(void *platform);
+int platform_set_channel_map(void *platform, int ch_count, char *ch_map,
+ int snd_id);
+int platform_set_stream_channel_map(void *platform, audio_channel_mask_t channel_mask, int snd_id);
+int platform_set_edid_channels_configuration(void *platform, int channels);
+unsigned char platform_map_to_edid_format(int format);
+bool platform_is_edid_supported_format(void *platform, int format);
+void platform_cache_edid(void * platform);
+void platform_invalidate_edid(void * platform);
+int platform_set_hdmi_config(struct stream_out *out);
+int platform_set_device_params(struct stream_out *out, int param, int value);
#endif // AUDIO_PLATFORM_API_H
diff --git a/hal/voice.c b/hal/voice.c
index 964b6f6..5fb0956 100644
--- a/hal/voice.c
+++ b/hal/voice.c
@@ -222,6 +222,11 @@
{
bool in_call_rec = false;
+ if (!in) {
+ ALOGE("%s: input stream is NULL", __func__);
+ return in_call_rec;
+ }
+
if(in->source == AUDIO_SOURCE_VOICE_DOWNLINK ||
in->source == AUDIO_SOURCE_VOICE_UPLINK ||
in->source == AUDIO_SOURCE_VOICE_CALL) {
@@ -309,6 +314,35 @@
return ret;
}
+snd_device_t voice_get_incall_rec_snd_device(snd_device_t in_snd_device)
+{
+ snd_device_t incall_record_device = in_snd_device;
+
+ /*
+ * For incall recording stream, AUDIO_COPP topology will be picked up
+ * from the calibration data of the input sound device which is nothing
+ * but the voice call's input device. But there are requirements to use
+ * AUDIO_COPP_MONO topology even if the voice call's input device is
+ * different. Hence override the input device with the one which uses
+ * the AUDIO_COPP_MONO topology.
+ */
+ switch(in_snd_device) {
+ case SND_DEVICE_IN_HANDSET_MIC:
+ case SND_DEVICE_IN_VOICE_DMIC:
+ case SND_DEVICE_IN_AANC_HANDSET_MIC:
+ incall_record_device = SND_DEVICE_IN_HANDSET_MIC;
+ case SND_DEVICE_IN_VOICE_SPEAKER_MIC:
+ case SND_DEVICE_IN_VOICE_SPEAKER_DMIC:
+ case SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BROADSIDE:
+ case SND_DEVICE_IN_VOICE_SPEAKER_QMIC:
+ incall_record_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
+ default:
+ incall_record_device = in_snd_device;
+ }
+
+ return incall_record_device;
+}
+
int voice_check_and_set_incall_music_usecase(struct audio_device *adev,
struct stream_out *out)
{
diff --git a/hal/voice.h b/hal/voice.h
index 9be8443..5038dfa 100644
--- a/hal/voice.h
+++ b/hal/voice.h
@@ -43,6 +43,7 @@
struct stream_in;
struct stream_out;
typedef int audio_usecase_t;
+typedef int snd_device_t;
struct call_state {
int current;
@@ -93,4 +94,5 @@
int voice_check_and_stop_incall_rec_usecase(struct audio_device *adev,
struct stream_in *in);
void voice_update_devices_for_all_voice_usecases(struct audio_device *adev);
+snd_device_t voice_get_incall_rec_snd_device(snd_device_t in_snd_device);
#endif //VOICE_H
diff --git a/post_proc/Android.mk b/post_proc/Android.mk
index 6ed1416..880838a 100644
--- a/post_proc/Android.mk
+++ b/post_proc/Android.mk
@@ -13,10 +13,16 @@
bass_boost.c \
virtualizer.c \
reverb.c \
- effect_api.c
+ effect_api.c \
+ effect_util.c \
+ hw_accelerator.c
LOCAL_CFLAGS+= -O2 -fvisibility=hidden
+ifneq ($(strip $(AUDIO_FEATURE_DISABLED_DTS_EAGLE)),true)
+ LOCAL_CFLAGS += -DDTS_EAGLE
+endif
+
LOCAL_SHARED_LIBRARIES := \
libcutils \
liblog \
@@ -27,9 +33,37 @@
LOCAL_MODULE_RELATIVE_PATH := soundfx
LOCAL_MODULE:= libqcompostprocbundle
+LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+
LOCAL_C_INCLUDES := \
external/tinyalsa/include \
$(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include \
$(call include-path-for, audio-effects)
include $(BUILD_SHARED_LIBRARY)
+
+
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_HW_ACCELERATED_EFFECTS)),true)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := EffectsHwAcc.cpp
+
+LOCAL_C_INCLUDES := \
+ $(call include-path-for, audio-effects)
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libeffects
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CFLAGS += -O2 -fvisibility=hidden
+
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_DTS_EAGLE)), true)
+LOCAL_CFLAGS += -DHW_ACC_HPX
+endif
+
+LOCAL_MODULE:= libhwacceffectswrapper
+
+include $(BUILD_STATIC_LIBRARY)
+endif
diff --git a/post_proc/EffectsHwAcc.cpp b/post_proc/EffectsHwAcc.cpp
new file mode 100644
index 0000000..0e4c55a
--- /dev/null
+++ b/post_proc/EffectsHwAcc.cpp
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) 2014, 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 "EffectsHwAcc"
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <media/EffectsFactoryApi.h>
+#include <audio_effects/effect_hwaccelerator.h>
+#include "EffectsHwAcc.h"
+
+namespace android {
+
+#define FRAME_SIZE(format) ((format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ? \
+ 3 /* bytes for 24 bit */ : \
+ (format == AUDIO_FORMAT_PCM_16_BIT) ? \
+ sizeof(uint16_t) : sizeof(uint8_t))
+// ----------------------------------------------------------------------------
+EffectsHwAcc::EffectsBufferProvider::EffectsBufferProvider()
+ : AudioBufferProvider(), mEffectsHandle(NULL),
+ mInputBuffer(NULL), mOutputBuffer(NULL),
+ mInputBufferFrameCountOffset(0)
+{
+}
+
+EffectsHwAcc::EffectsBufferProvider::~EffectsBufferProvider()
+{
+ ALOGV(" deleting HwAccEffBufferProvider");
+
+ if (mEffectsHandle)
+ EffectRelease(mEffectsHandle);
+ if (mInputBuffer)
+ free(mInputBuffer);
+ if (mOutputBuffer)
+ free(mOutputBuffer);
+}
+
+status_t EffectsHwAcc::EffectsBufferProvider::getNextBuffer(
+ AudioBufferProvider::Buffer *pBuffer,
+ int64_t pts)
+{
+ ALOGV("EffectsBufferProvider::getNextBuffer");
+
+ size_t reqInputFrameCount, frameCount, offset;
+ size_t reqOutputFrameCount = pBuffer->frameCount;
+ int ret = 0;
+
+ if (mTrackBufferProvider != NULL) {
+ while (1) {
+ reqInputFrameCount = ((reqOutputFrameCount *
+ mEffectsConfig.inputCfg.samplingRate)/
+ mEffectsConfig.outputCfg.samplingRate) +
+ (((reqOutputFrameCount *
+ mEffectsConfig.inputCfg.samplingRate)%
+ mEffectsConfig.outputCfg.samplingRate) ? 1 : 0);
+ ALOGV("InputFrameCount: %d, OutputFrameCount: %d, InputBufferFrameCountOffset: %d",
+ reqInputFrameCount, reqOutputFrameCount,
+ mInputBufferFrameCountOffset);
+ frameCount = reqInputFrameCount - mInputBufferFrameCountOffset;
+ offset = mInputBufferFrameCountOffset *
+ FRAME_SIZE(mEffectsConfig.inputCfg.format) *
+ popcount(mEffectsConfig.inputCfg.channels);
+ while (frameCount) {
+ pBuffer->frameCount = frameCount;
+ ret = mTrackBufferProvider->getNextBuffer(pBuffer, pts);
+ if (ret == OK) {
+ int bytesInBuffer = pBuffer->frameCount *
+ FRAME_SIZE(mEffectsConfig.inputCfg.format) *
+ popcount(mEffectsConfig.inputCfg.channels);
+ memcpy((char *)mInputBuffer+offset, pBuffer->i8, bytesInBuffer);
+ frameCount -= pBuffer->frameCount;
+ mInputBufferFrameCountOffset += pBuffer->frameCount;
+ offset += bytesInBuffer;
+ mTrackBufferProvider->releaseBuffer(pBuffer);
+ } else
+ break;
+ }
+ if (ret == OK) {
+ mEffectsConfig.inputCfg.buffer.frameCount = reqInputFrameCount;
+ mEffectsConfig.inputCfg.buffer.raw = (void *)mInputBuffer;
+ mEffectsConfig.outputCfg.buffer.frameCount = reqOutputFrameCount;
+ mEffectsConfig.outputCfg.buffer.raw = (void *)mOutputBuffer;
+
+ ret = (*mEffectsHandle)->process(mEffectsHandle,
+ &mEffectsConfig.inputCfg.buffer,
+ &mEffectsConfig.outputCfg.buffer);
+ if (ret == -ENODATA) {
+ ALOGV("Continue to provide more data for initial buffering");
+ mInputBufferFrameCountOffset -= reqInputFrameCount;
+ continue;
+ }
+ if (ret > 0)
+ mInputBufferFrameCountOffset -= reqInputFrameCount;
+ pBuffer->raw = (void *)mOutputBuffer;
+ pBuffer->frameCount = reqOutputFrameCount;
+ }
+ return ret;
+ }
+ } else {
+ ALOGE("EffBufferProvider::getNextBuffer() error: NULL track buffer provider");
+ return NO_INIT;
+ }
+}
+
+void EffectsHwAcc::EffectsBufferProvider::releaseBuffer(
+ AudioBufferProvider::Buffer *pBuffer)
+{
+ ALOGV("EffBufferProvider::releaseBuffer()");
+ if (this->mTrackBufferProvider != NULL) {
+ pBuffer->frameCount = 0;
+ pBuffer->raw = NULL;
+ } else {
+ ALOGE("HwAccEffectsBufferProvider::releaseBuffer() error: NULL track buffer provider");
+ }
+}
+
+EffectsHwAcc::EffectsHwAcc(uint32_t sampleRate)
+ : mEnabled(false), mFd(-1), mBufferProvider(NULL),
+ mInputSampleRate(sampleRate), mOutputSampleRate(sampleRate)
+{
+}
+
+EffectsHwAcc::~EffectsHwAcc()
+{
+ ALOGV("deleting EffectsHwAcc");
+
+ if (mBufferProvider)
+ delete mBufferProvider;
+}
+
+void EffectsHwAcc::setSampleRate(uint32_t inpSR, uint32_t outSR)
+{
+ mInputSampleRate = inpSR;
+ mOutputSampleRate = outSR;
+}
+
+void EffectsHwAcc::unprepareEffects(AudioBufferProvider **bufferProvider)
+{
+ ALOGV("EffectsHwAcc::unprepareEffects");
+
+ EffectsBufferProvider *pHwAccbp = mBufferProvider;
+ if (mBufferProvider != NULL) {
+ ALOGV(" deleting h/w accelerator EffectsBufferProvider");
+ int cmdStatus, status;
+ uint32_t replySize = sizeof(int);
+
+ replySize = sizeof(int);
+ status = (*pHwAccbp->mEffectsHandle)->command(pHwAccbp->mEffectsHandle,
+ EFFECT_CMD_DISABLE,
+ 0 /*cmdSize*/, NULL /*pCmdData*/,
+ &replySize, &cmdStatus /*pReplyData*/);
+ if ((status != 0) || (cmdStatus != 0))
+ ALOGE("error %d while enabling hw acc effects", status);
+
+ *bufferProvider = pHwAccbp->mTrackBufferProvider;
+ delete mBufferProvider;
+
+ mBufferProvider = NULL;
+ } else {
+ ALOGV(" nothing to do, no h/w accelerator effects to delete");
+ }
+ mEnabled = false;
+}
+
+status_t EffectsHwAcc::prepareEffects(AudioBufferProvider **bufferProvider,
+ int sessionId,
+ audio_channel_mask_t channelMask,
+ int frameCount)
+{
+ ALOGV("EffectsHwAcc::prepareAccEffects");
+
+ // discard the previous hw acc effects if there was one
+ unprepareEffects(bufferProvider);
+
+ EffectsBufferProvider* pHwAccbp = new EffectsBufferProvider();
+ int32_t status;
+ int cmdStatus;
+ uint32_t replySize;
+ uint32_t size = (sizeof(effect_param_t) + 2 * sizeof(int32_t) - 1) /
+ (sizeof(uint32_t) + 1);
+ uint32_t buf32[size];
+ effect_param_t *param = (effect_param_t *)buf32;
+
+ uint32_t i, numEffects = 0;
+ effect_descriptor_t hwAccFxDesc;
+ int ret = EffectQueryNumberEffects(&numEffects);
+ if (ret != 0) {
+ ALOGE("AudioMixer() error %d querying number of effects", ret);
+ goto noEffectsForActiveTrack;
+ }
+ ALOGV("EffectQueryNumberEffects() numEffects=%d", numEffects);
+
+ for (i = 0 ; i < numEffects ; i++) {
+ if (EffectQueryEffect(i, &hwAccFxDesc) == 0) {
+ if (memcmp(&hwAccFxDesc.type, EFFECT_UIID_HWACCELERATOR,
+ sizeof(effect_uuid_t)) == 0) {
+ ALOGI("found effect \"%s\" from %s",
+ hwAccFxDesc.name, hwAccFxDesc.implementor);
+ break;
+ }
+ }
+ }
+ if (i == numEffects) {
+ ALOGW("H/W accelerated effects library not found");
+ goto noEffectsForActiveTrack;
+ }
+ if (EffectCreate(&hwAccFxDesc.uuid, sessionId, -1 /*ioId not relevant here*/,
+ &pHwAccbp->mEffectsHandle) != 0) {
+ ALOGE("prepareEffects fails: error creating effect");
+ goto noEffectsForActiveTrack;
+ }
+
+ // channel input configuration will be overridden per-track
+ pHwAccbp->mEffectsConfig.inputCfg.channels = channelMask;
+ pHwAccbp->mEffectsConfig.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
+ pHwAccbp->mEffectsConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ pHwAccbp->mEffectsConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ pHwAccbp->mEffectsConfig.inputCfg.samplingRate = mInputSampleRate;
+ pHwAccbp->mEffectsConfig.outputCfg.samplingRate = mOutputSampleRate;
+ pHwAccbp->mEffectsConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
+ pHwAccbp->mEffectsConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
+ pHwAccbp->mEffectsConfig.outputCfg.buffer.frameCount = frameCount;
+ pHwAccbp->mEffectsConfig.inputCfg.mask = EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS |
+ EFFECT_CONFIG_FORMAT | EFFECT_CONFIG_ACC_MODE;
+ pHwAccbp->mEffectsConfig.outputCfg.mask = pHwAccbp->mEffectsConfig.inputCfg.mask;
+
+ // Configure hw acc effects
+ replySize = sizeof(int);
+ status = (*pHwAccbp->mEffectsHandle)->command(pHwAccbp->mEffectsHandle,
+ EFFECT_CMD_SET_CONFIG,
+ sizeof(effect_config_t) /*cmdSize*/,
+ &pHwAccbp->mEffectsConfig /*pCmdData*/,
+ &replySize, &cmdStatus /*pReplyData*/);
+ if ((status != 0) || (cmdStatus != 0)) {
+ ALOGE("error %d while configuring h/w acc effects", status);
+ goto noEffectsForActiveTrack;
+ }
+ replySize = sizeof(int);
+ status = (*pHwAccbp->mEffectsHandle)->command(pHwAccbp->mEffectsHandle,
+ EFFECT_CMD_HW_ACC,
+ sizeof(frameCount) /*cmdSize*/,
+ &frameCount /*pCmdData*/,
+ &replySize,
+ &cmdStatus /*pReplyData*/);
+ if ((status != 0) || (cmdStatus != 0)) {
+ ALOGE("error %d while enabling h/w acc effects", status);
+ goto noEffectsForActiveTrack;
+ }
+ replySize = sizeof(int);
+ status = (*pHwAccbp->mEffectsHandle)->command(pHwAccbp->mEffectsHandle,
+ EFFECT_CMD_ENABLE,
+ 0 /*cmdSize*/, NULL /*pCmdData*/,
+ &replySize, &cmdStatus /*pReplyData*/);
+ if ((status != 0) || (cmdStatus != 0)) {
+ ALOGE("error %d while enabling h/w acc effects", status);
+ goto noEffectsForActiveTrack;
+ }
+
+ param->psize = sizeof(int32_t);
+ *(int32_t *)param->data = HW_ACCELERATOR_FD;
+ param->vsize = sizeof(int32_t);
+ replySize = sizeof(effect_param_t) +
+ ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
+ param->vsize;
+ status = (*pHwAccbp->mEffectsHandle)->command(pHwAccbp->mEffectsHandle,
+ EFFECT_CMD_GET_PARAM,
+ sizeof(effect_param_t) + param->psize,
+ param, &replySize, param);
+ if ((param->status != 0) || (*(int32_t *)(param->data + sizeof(int32_t)) <= 0)) {
+ ALOGE("error %d while enabling h/w acc effects", status);
+ goto noEffectsForActiveTrack;
+ }
+ mFd = *(int32_t *)(param->data + sizeof(int32_t));
+
+ pHwAccbp->mInputBuffer = calloc(6*frameCount,
+ /* 6 times buffering to account for an input of
+ 192kHz to an output of 32kHz - may be a least
+ sampling rate of rendering device */
+ FRAME_SIZE(pHwAccbp->mEffectsConfig.inputCfg.format) *
+ popcount(channelMask));
+ if (!pHwAccbp->mInputBuffer)
+ goto noEffectsForActiveTrack;
+
+ pHwAccbp->mOutputBuffer = calloc(frameCount,
+ FRAME_SIZE(pHwAccbp->mEffectsConfig.outputCfg.format) *
+ popcount(AUDIO_CHANNEL_OUT_STEREO));
+ if (!pHwAccbp->mOutputBuffer) {
+ free(pHwAccbp->mInputBuffer);
+ goto noEffectsForActiveTrack;
+ }
+ // initialization successful:
+ // - keep track of the real buffer provider in case it was set before
+ pHwAccbp->mTrackBufferProvider = *bufferProvider;
+ // - we'll use the hw acc effect integrated inside this
+ // track's buffer provider, and we'll use it as the track's buffer provider
+ mBufferProvider = pHwAccbp;
+ *bufferProvider = pHwAccbp;
+
+ mEnabled = true;
+ return NO_ERROR;
+
+noEffectsForActiveTrack:
+ delete pHwAccbp;
+ mBufferProvider = NULL;
+ return NO_INIT;
+}
+
+void EffectsHwAcc::setBufferProvider(AudioBufferProvider **bufferProvider,
+ AudioBufferProvider **trackBufferProvider)
+{
+ ALOGV("setBufferProvider");
+ if (mBufferProvider &&
+ (mBufferProvider->mTrackBufferProvider != *bufferProvider)) {
+ *trackBufferProvider = mBufferProvider;
+ mBufferProvider->mTrackBufferProvider = *bufferProvider;
+ }
+}
+
+#ifdef HW_ACC_HPX
+void EffectsHwAcc::updateHPXState(uint32_t state)
+{
+ EffectsBufferProvider *pHwAccbp = mBufferProvider;
+ if (pHwAccbp) {
+ ALOGV("updateHPXState: %d", state);
+ int cmdStatus, status;
+ uint32_t replySize = sizeof(int);
+ uint32_t data = state;
+ uint32_t size = (sizeof(effect_param_t) + 2 * sizeof(int32_t));
+ uint32_t buf32[size];
+ effect_param_t *param = (effect_param_t *)buf32;
+
+ param->psize = sizeof(int32_t);
+ *(int32_t *)param->data = HW_ACCELERATOR_HPX_STATE;
+ param->vsize = sizeof(int32_t);
+ memcpy((param->data + param->psize), &data, param->vsize);
+ status = (*pHwAccbp->mEffectsHandle)->command(pHwAccbp->mEffectsHandle,
+ EFFECT_CMD_SET_PARAM,
+ sizeof(effect_param_t) + param->psize +
+ param->vsize,
+ param, &replySize, &cmdStatus);
+
+ if ((status != 0) || (cmdStatus != 0))
+ ALOGE("error %d while updating HW ACC HPX BYPASS state", status);
+ }
+}
+#endif
+// ----------------------------------------------------------------------------
+}; // namespace android
diff --git a/post_proc/EffectsHwAcc.h b/post_proc/EffectsHwAcc.h
new file mode 100644
index 0000000..6420a9b
--- /dev/null
+++ b/post_proc/EffectsHwAcc.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2014, 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 ANDROID_EFFECTS_HW_ACC_H
+#define ANDROID_EFFECTS_HW_ACC_H
+
+#include <media/AudioBufferProvider.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+class EffectsHwAcc {
+public:
+ EffectsHwAcc(uint32_t sampleRate);
+ virtual ~EffectsHwAcc();
+
+ virtual void setSampleRate(uint32_t inpSR, uint32_t outSR);
+ virtual void unprepareEffects(AudioBufferProvider **trackBufferProvider);
+ virtual status_t prepareEffects(AudioBufferProvider **trackBufferProvider,
+ int sessionId, audio_channel_mask_t channelMask,
+ int frameCount);
+ virtual void setBufferProvider(AudioBufferProvider **bufferProvider,
+ AudioBufferProvider **trackBufferProvider);
+#ifdef HW_ACC_HPX
+ virtual void updateHPXState(uint32_t state);
+#endif
+
+ /* AudioBufferProvider that wraps a track AudioBufferProvider by a call to
+ h/w accelerated effect */
+ class EffectsBufferProvider : public AudioBufferProvider {
+ public:
+ EffectsBufferProvider();
+ virtual ~EffectsBufferProvider();
+
+ virtual status_t getNextBuffer(Buffer* buffer, int64_t pts);
+ virtual void releaseBuffer(Buffer* buffer);
+
+ AudioBufferProvider* mTrackBufferProvider;
+ effect_handle_t mEffectsHandle;
+ effect_config_t mEffectsConfig;
+
+ void *mInputBuffer;
+ void *mOutputBuffer;
+ uint32_t mInputBufferFrameCountOffset;
+ };
+
+ bool mEnabled;
+ int32_t mFd;
+
+ EffectsBufferProvider* mBufferProvider;
+
+private:
+ uint32_t mInputSampleRate;
+ uint32_t mOutputSampleRate;
+};
+
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_EFFECTS_HW_ACC_H
diff --git a/post_proc/bass_boost.c b/post_proc/bass_boost.c
index e2c6d9a..57cf8ef 100644
--- a/post_proc/bass_boost.c
+++ b/post_proc/bass_boost.c
@@ -18,7 +18,7 @@
*/
#define LOG_TAG "offload_effect_bass_boost"
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
#include <cutils/list.h>
#include <cutils/log.h>
@@ -59,9 +59,14 @@
offload_bassboost_set_strength(&(context->offload_bass), strength);
if (context->ctl)
- offload_bassboost_send_params(context->ctl, context->offload_bass,
+ offload_bassboost_send_params(context->ctl, &context->offload_bass,
OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG |
OFFLOAD_SEND_BASSBOOST_STRENGTH);
+ if (context->hw_acc_fd > 0)
+ hw_acc_bassboost_send_params(context->hw_acc_fd,
+ &context->offload_bass,
+ OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG |
+ OFFLOAD_SEND_BASSBOOST_STRENGTH);
return 0;
}
@@ -117,7 +122,7 @@
}
int bassboost_set_parameter(effect_context_t *context, effect_param_t *p,
- uint32_t size)
+ uint32_t size __unused)
{
bassboost_context_t *bass_ctxt = (bassboost_context_t *)context;
int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
@@ -163,8 +168,12 @@
offload_bassboost_set_enable_flag(&(bass_ctxt->offload_bass), false);
if (bass_ctxt->ctl)
offload_bassboost_send_params(bass_ctxt->ctl,
- bass_ctxt->offload_bass,
+ &bass_ctxt->offload_bass,
OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG);
+ if (bass_ctxt->hw_acc_fd > 0)
+ hw_acc_bassboost_send_params(bass_ctxt->hw_acc_fd,
+ &bass_ctxt->offload_bass,
+ OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG);
}
bass_ctxt->temp_disabled = true;
}
@@ -175,8 +184,12 @@
offload_bassboost_set_enable_flag(&(bass_ctxt->offload_bass), true);
if (bass_ctxt->ctl)
offload_bassboost_send_params(bass_ctxt->ctl,
- bass_ctxt->offload_bass,
+ &bass_ctxt->offload_bass,
OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG);
+ if (bass_ctxt->hw_acc_fd > 0)
+ hw_acc_bassboost_send_params(bass_ctxt->hw_acc_fd,
+ &bass_ctxt->offload_bass,
+ OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG);
}
bass_ctxt->temp_disabled = false;
}
@@ -216,6 +229,7 @@
set_config(context, &context->config);
+ bass_ctxt->hw_acc_fd = -1;
bass_ctxt->temp_disabled = false;
memset(&(bass_ctxt->offload_bass), 0, sizeof(struct bass_boost_params));
@@ -233,9 +247,14 @@
offload_bassboost_set_enable_flag(&(bass_ctxt->offload_bass), true);
if (bass_ctxt->ctl && bass_ctxt->strength)
offload_bassboost_send_params(bass_ctxt->ctl,
- bass_ctxt->offload_bass,
+ &bass_ctxt->offload_bass,
OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG |
OFFLOAD_SEND_BASSBOOST_STRENGTH);
+ if ((bass_ctxt->hw_acc_fd > 0) && (bass_ctxt->strength))
+ hw_acc_bassboost_send_params(bass_ctxt->hw_acc_fd,
+ &bass_ctxt->offload_bass,
+ OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG |
+ OFFLOAD_SEND_BASSBOOST_STRENGTH);
}
return 0;
}
@@ -249,8 +268,12 @@
offload_bassboost_set_enable_flag(&(bass_ctxt->offload_bass), false);
if (bass_ctxt->ctl)
offload_bassboost_send_params(bass_ctxt->ctl,
- bass_ctxt->offload_bass,
+ &bass_ctxt->offload_bass,
OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG);
+ if (bass_ctxt->hw_acc_fd > 0)
+ hw_acc_bassboost_send_params(bass_ctxt->hw_acc_fd,
+ &bass_ctxt->offload_bass,
+ OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG);
}
return 0;
}
@@ -262,19 +285,47 @@
ALOGV("%s: ctxt %p, ctl %p, strength %d", __func__, bass_ctxt,
output->ctl, bass_ctxt->strength);
bass_ctxt->ctl = output->ctl;
- if (offload_bassboost_get_enable_flag(&(bass_ctxt->offload_bass)))
+ if (offload_bassboost_get_enable_flag(&(bass_ctxt->offload_bass))) {
if (bass_ctxt->ctl)
- offload_bassboost_send_params(bass_ctxt->ctl, bass_ctxt->offload_bass,
+ offload_bassboost_send_params(bass_ctxt->ctl, &bass_ctxt->offload_bass,
OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG |
OFFLOAD_SEND_BASSBOOST_STRENGTH);
+ if (bass_ctxt->hw_acc_fd > 0)
+ hw_acc_bassboost_send_params(bass_ctxt->hw_acc_fd,
+ &bass_ctxt->offload_bass,
+ OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG |
+ OFFLOAD_SEND_BASSBOOST_STRENGTH);
+ }
return 0;
}
-int bassboost_stop(effect_context_t *context, output_context_t *output)
+int bassboost_stop(effect_context_t *context, output_context_t *output __unused)
{
bassboost_context_t *bass_ctxt = (bassboost_context_t *)context;
ALOGV("%s: ctxt %p", __func__, bass_ctxt);
+ if (offload_bassboost_get_enable_flag(&(bass_ctxt->offload_bass)) &&
+ bass_ctxt->ctl) {
+ struct bass_boost_params bassboost;
+ bassboost.enable_flag = false;
+ offload_bassboost_send_params(bass_ctxt->ctl, &bassboost,
+ OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG);
+ }
bass_ctxt->ctl = NULL;
return 0;
}
+
+int bassboost_set_mode(effect_context_t *context, int32_t hw_acc_fd)
+{
+ bassboost_context_t *bass_ctxt = (bassboost_context_t *)context;
+
+ ALOGV("%s: ctxt %p", __func__, bass_ctxt);
+ bass_ctxt->hw_acc_fd = hw_acc_fd;
+ if ((bass_ctxt->hw_acc_fd > 0) &&
+ (offload_bassboost_get_enable_flag(&(bass_ctxt->offload_bass))))
+ hw_acc_bassboost_send_params(bass_ctxt->hw_acc_fd,
+ &bass_ctxt->offload_bass,
+ OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG |
+ OFFLOAD_SEND_BASSBOOST_STRENGTH);
+ return 0;
+}
diff --git a/post_proc/bass_boost.h b/post_proc/bass_boost.h
index 430a07d..6f0e61b 100644
--- a/post_proc/bass_boost.h
+++ b/post_proc/bass_boost.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -31,6 +31,7 @@
// Offload vars
struct mixer_ctl *ctl;
+ int hw_acc_fd;
bool temp_disabled;
uint32_t device;
struct bass_boost_params offload_bass;
@@ -44,6 +45,8 @@
int bassboost_set_device(effect_context_t *context, uint32_t device);
+int bassboost_set_mode(effect_context_t *context, int32_t hw_acc_fd);
+
int bassboost_reset(effect_context_t *context);
int bassboost_init(effect_context_t *context);
diff --git a/post_proc/bundle.c b/post_proc/bundle.c
index 0db2e37..410e17b 100644
--- a/post_proc/bundle.c
+++ b/post_proc/bundle.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -15,10 +15,28 @@
* 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.
+ *
+ * This file was modified by DTS, Inc. The portions of the
+ * code modified by DTS, Inc are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2014 DTS, Inc.
+ *
+ * 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 "offload_effect_bundle"
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
#include <cutils/list.h>
#include <cutils/log.h>
@@ -27,11 +45,16 @@
#include <hardware/audio_effect.h>
#include "bundle.h"
+#include "hw_accelerator.h"
#include "equalizer.h"
#include "bass_boost.h"
#include "virtualizer.h"
#include "reverb.h"
+#ifdef DTS_EAGLE
+#include "effect_util.h"
+#endif
+
enum {
EFFECT_STATE_UNINITIALIZED,
EFFECT_STATE_INITIALIZED,
@@ -46,6 +69,7 @@
&ins_env_reverb_descriptor,
&aux_preset_reverb_descriptor,
&ins_preset_reverb_descriptor,
+ &hw_accelerator_descriptor,
NULL,
};
@@ -190,6 +214,10 @@
ALOGV("%s output %d pcm_id %d", __func__, output, pcm_id);
+#ifdef DTS_EAGLE
+ create_effect_state_node(pcm_id);
+#endif
+
if (lib_init() != 0)
return init_status;
@@ -217,6 +245,7 @@
if (!out_ctxt->mixer) {
ALOGE("Failed to open mixer");
out_ctxt->ctl = NULL;
+ out_ctxt->ref_ctl = NULL;
ret = -EINVAL;
free(out_ctxt);
goto exit;
@@ -230,6 +259,7 @@
free(out_ctxt);
goto exit;
}
+ out_ctxt->ref_ctl = out_ctxt->ctl;
}
list_init(&out_ctxt->effects_list);
@@ -285,6 +315,10 @@
list_remove(&out_ctxt->outputs_list_node);
+#ifdef DTS_EAGLE
+ remove_effect_state_node(pcm_id);
+#endif
+
free(out_ctxt);
exit:
@@ -292,6 +326,131 @@
return ret;
}
+__attribute__ ((visibility ("default")))
+int offload_effects_bundle_set_hpx_state(bool hpx_state)
+{
+ int ret = 0;
+ struct listnode *node;
+
+ ALOGV("%s hpx state: %d", __func__, hpx_state);
+
+ if (lib_init() != 0)
+ return init_status;
+
+ pthread_mutex_lock(&lock);
+
+ if (hpx_state) {
+ /* set ramp down */
+ list_for_each(node, &active_outputs_list) {
+ output_context_t *out_ctxt = node_to_item(node,
+ output_context_t,
+ outputs_list_node);
+ struct soft_volume_params vol;
+ vol.master_gain = 0x0;
+ offload_transition_soft_volume_send_params(out_ctxt->ref_ctl, vol,
+ OFFLOAD_SEND_TRANSITION_SOFT_VOLUME_GAIN_MASTER);
+ }
+ /* wait for ramp down duration - 30msec */
+ usleep(30000);
+ /* disable effects modules */
+ list_for_each(node, &active_outputs_list) {
+ struct listnode *fx_node;
+ output_context_t *out_ctxt = node_to_item(node,
+ output_context_t,
+ outputs_list_node);
+ list_for_each(fx_node, &out_ctxt->effects_list) {
+ effect_context_t *fx_ctxt = node_to_item(fx_node,
+ effect_context_t,
+ output_node);
+ if ((fx_ctxt->state == EFFECT_STATE_ACTIVE) &&
+ (fx_ctxt->ops.stop != NULL))
+ fx_ctxt->ops.stop(fx_ctxt, out_ctxt);
+ }
+ out_ctxt->ctl = NULL;
+ }
+ /* set the channel mixer */
+ list_for_each(node, &active_outputs_list) {
+ /* send command to set channel mixer */
+ }
+ /* enable hpx modules */
+ list_for_each(node, &active_outputs_list) {
+ output_context_t *out_ctxt = node_to_item(node,
+ output_context_t,
+ outputs_list_node);
+ offload_hpx_send_params(out_ctxt->ref_ctl,
+ OFFLOAD_SEND_HPX_STATE_ON);
+ }
+ /* wait for transition state - 50msec */
+ usleep(50000);
+ /* set ramp up */
+ list_for_each(node, &active_outputs_list) {
+ output_context_t *out_ctxt = node_to_item(node,
+ output_context_t,
+ outputs_list_node);
+ struct soft_volume_params vol;
+ vol.master_gain = 0x2000;
+ offload_transition_soft_volume_send_params(out_ctxt->ref_ctl, vol,
+ OFFLOAD_SEND_TRANSITION_SOFT_VOLUME_GAIN_MASTER);
+ }
+ } else {
+ /* set ramp down */
+ list_for_each(node, &active_outputs_list) {
+ output_context_t *out_ctxt = node_to_item(node,
+ output_context_t,
+ outputs_list_node);
+ struct soft_volume_params vol;
+ vol.master_gain = 0x0;
+ offload_transition_soft_volume_send_params(out_ctxt->ref_ctl, vol,
+ OFFLOAD_SEND_TRANSITION_SOFT_VOLUME_GAIN_MASTER);
+ }
+ /* wait for ramp down duration - 30msec */
+ usleep(30000);
+ /* disable effects modules */
+ list_for_each(node, &active_outputs_list) {
+ output_context_t *out_ctxt = node_to_item(node,
+ output_context_t,
+ outputs_list_node);
+ offload_hpx_send_params(out_ctxt->ref_ctl,
+ OFFLOAD_SEND_HPX_STATE_OFF);
+ }
+ /* set the channel mixer */
+ list_for_each(node, &active_outputs_list) {
+ /* send command to set channel mixer */
+ }
+ /* enable effects modules */
+ list_for_each(node, &active_outputs_list) {
+ struct listnode *fx_node;
+ output_context_t *out_ctxt = node_to_item(node,
+ output_context_t,
+ outputs_list_node);
+ out_ctxt->ctl = out_ctxt->ref_ctl;
+ list_for_each(fx_node, &out_ctxt->effects_list) {
+ effect_context_t *fx_ctxt = node_to_item(fx_node,
+ effect_context_t,
+ output_node);
+ if ((fx_ctxt->state == EFFECT_STATE_ACTIVE) &&
+ (fx_ctxt->ops.start != NULL))
+ fx_ctxt->ops.start(fx_ctxt, out_ctxt);
+ }
+ }
+ /* wait for transition state - 50msec */
+ usleep(50000);
+ /* set ramp up */
+ list_for_each(node, &active_outputs_list) {
+ output_context_t *out_ctxt = node_to_item(node,
+ output_context_t,
+ outputs_list_node);
+ struct soft_volume_params vol;
+ vol.master_gain = 0x2000;
+ offload_transition_soft_volume_send_params(out_ctxt->ref_ctl, vol,
+ OFFLOAD_SEND_TRANSITION_SOFT_VOLUME_GAIN_MASTER);
+ }
+ }
+
+exit:
+ pthread_mutex_unlock(&lock);
+ return ret;
+}
/*
* Effect operations
@@ -351,6 +510,7 @@
context->ops.set_parameter = equalizer_set_parameter;
context->ops.get_parameter = equalizer_get_parameter;
context->ops.set_device = equalizer_set_device;
+ context->ops.set_hw_acc_mode = equalizer_set_mode;
context->ops.enable = equalizer_enable;
context->ops.disable = equalizer_disable;
context->ops.start = equalizer_start;
@@ -371,6 +531,7 @@
context->ops.set_parameter = bassboost_set_parameter;
context->ops.get_parameter = bassboost_get_parameter;
context->ops.set_device = bassboost_set_device;
+ context->ops.set_hw_acc_mode = bassboost_set_mode;
context->ops.enable = bassboost_enable;
context->ops.disable = bassboost_disable;
context->ops.start = bassboost_start;
@@ -391,6 +552,7 @@
context->ops.set_parameter = virtualizer_set_parameter;
context->ops.get_parameter = virtualizer_get_parameter;
context->ops.set_device = virtualizer_set_device;
+ context->ops.set_hw_acc_mode = virtualizer_set_mode;
context->ops.enable = virtualizer_enable;
context->ops.disable = virtualizer_disable;
context->ops.start = virtualizer_start;
@@ -417,6 +579,7 @@
context->ops.set_parameter = reverb_set_parameter;
context->ops.get_parameter = reverb_get_parameter;
context->ops.set_device = reverb_set_device;
+ context->ops.set_hw_acc_mode = reverb_set_mode;
context->ops.enable = reverb_enable;
context->ops.disable = reverb_disable;
context->ops.start = reverb_start;
@@ -429,7 +592,7 @@
} else if (memcmp(uuid, &ins_env_reverb_descriptor.uuid,
sizeof(effect_uuid_t)) == 0) {
context->desc = &ins_env_reverb_descriptor;
- reverb_preset_init(reverb_ctxt);
+ reverb_insert_init(reverb_ctxt);
} else if (memcmp(uuid, &aux_preset_reverb_descriptor.uuid,
sizeof(effect_uuid_t)) == 0) {
context->desc = &aux_preset_reverb_descriptor;
@@ -440,6 +603,27 @@
reverb_preset_init(reverb_ctxt);
}
reverb_ctxt->ctl = NULL;
+ } else if (memcmp(uuid, &hw_accelerator_descriptor.uuid,
+ sizeof(effect_uuid_t)) == 0) {
+ hw_accelerator_context_t *hw_acc_ctxt = (hw_accelerator_context_t *)
+ calloc(1, sizeof(hw_accelerator_context_t));
+ if (hw_acc_ctxt == NULL) {
+ ALOGE("h/w acc context allocation failed");
+ return -ENOMEM;
+ }
+ context = (effect_context_t *)hw_acc_ctxt;
+ context->ops.init = hw_accelerator_init;
+ context->ops.reset = hw_accelerator_reset;
+ context->ops.set_parameter = hw_accelerator_set_parameter;
+ context->ops.get_parameter = hw_accelerator_get_parameter;
+ context->ops.set_device = hw_accelerator_set_device;
+ context->ops.set_hw_acc_mode = hw_accelerator_set_mode;
+ context->ops.enable = hw_accelerator_enable;
+ context->ops.disable = hw_accelerator_disable;
+ context->ops.release = hw_accelerator_release;
+ context->ops.process = hw_accelerator_process;
+
+ context->desc = &hw_accelerator_descriptor;
} else {
return -EINVAL;
}
@@ -527,6 +711,7 @@
*/
/* Stub function for effect interface: never called for offloaded effects */
+/* called for hw accelerated effects */
int effect_process(effect_handle_t self,
audio_buffer_t *inBuffer,
audio_buffer_t *outBuffer)
@@ -534,7 +719,7 @@
effect_context_t * context = (effect_context_t *)self;
int status = 0;
- ALOGW("%s: ctxt %p, Called ?????", __func__, context);
+ ALOGV("%s", __func__);
pthread_mutex_lock(&lock);
if (!effect_exists(context)) {
@@ -547,6 +732,8 @@
goto exit;
}
+ if (context->ops.process)
+ status = context->ops.process(context, inBuffer, outBuffer);
exit:
pthread_mutex_unlock(&lock);
return status;
@@ -598,7 +785,7 @@
status = -EINVAL;
goto exit;
}
- if (!context->offload_enabled) {
+ if (!context->offload_enabled && !context->hw_acc_enabled) {
status = -EINVAL;
goto exit;
}
@@ -648,7 +835,7 @@
cmdSize, *replySize);
goto exit;
}
- if (!context->offload_enabled) {
+ if (!context->offload_enabled && !context->hw_acc_enabled) {
status = -EINVAL;
goto exit;
}
@@ -723,7 +910,20 @@
} break;
+ case EFFECT_CMD_HW_ACC: {
+ ALOGV("EFFECT_CMD_HW_ACC cmdSize %d pCmdData %p, *replySize %d, pReplyData %p",
+ cmdSize, pCmdData, *replySize, pReplyData);
+ if (cmdSize != sizeof(uint32_t) || pCmdData == NULL
+ || pReplyData == NULL || *replySize != sizeof(int)) {
+ return -EINVAL;
+ }
+ uint32_t value = *(uint32_t *)pCmdData;
+ if (context->ops.set_hw_acc_mode)
+ context->ops.set_hw_acc_mode(context, value);
+ context->hw_acc_enabled = (value > 0) ? true : false;
+ break;
+ }
default:
if (cmdCode >= EFFECT_CMD_FIRST_PROPRIETARY && context->ops.command)
status = context->ops.command(context, cmdCode, cmdSize,
diff --git a/post_proc/bundle.h b/post_proc/bundle.h
index cbe7dba..06da991 100644
--- a/post_proc/bundle.h
+++ b/post_proc/bundle.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
* Not a contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -48,6 +48,7 @@
int pcm_device_id;
struct mixer *mixer;
struct mixer_ctl *ctl;
+ struct mixer_ctl *ref_ctl;
};
/* effect specific operations.
@@ -66,6 +67,7 @@
int (*set_parameter)(effect_context_t *context, effect_param_t *param, uint32_t size);
int (*get_parameter)(effect_context_t *context, effect_param_t *param, uint32_t *size);
int (*set_device)(effect_context_t *context, uint32_t device);
+ int (*set_hw_acc_mode)(effect_context_t *context, int32_t value);
int (*command)(effect_context_t *context, uint32_t cmdCode, uint32_t cmdSize,
void *pCmdData, uint32_t *replySize, void *pReplyData);
};
@@ -82,6 +84,7 @@
audio_io_handle_t out_handle;
uint32_t state;
bool offload_enabled;
+ bool hw_acc_enabled;
effect_ops_t ops;
};
diff --git a/post_proc/effect_api.c b/post_proc/effect_api.c
index 971b67f..7c1968e 100644
--- a/post_proc/effect_api.c
+++ b/post_proc/effect_api.c
@@ -25,10 +25,28 @@
* 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.
+ *
+ * This file was modified by DTS, Inc. The portions of the
+ * code modified by DTS, Inc are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2014 DTS, Inc.
+ *
+ * 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 "offload_effect_api"
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
//#define VERY_VERY_VERBOSE_LOGGING
#ifdef VERY_VERY_VERBOSE_LOGGING
#define ALOGVV ALOGV
@@ -40,10 +58,20 @@
#include <cutils/log.h>
#include <tinyalsa/asoundlib.h>
#include <sound/audio_effects.h>
+#include <sound/devdep_params.h>
+#include <linux/msm_audio.h>
#include "effect_api.h"
+#ifdef DTS_EAGLE
+#include "effect_util.h"
+#endif
+
#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
+typedef enum eff_mode {
+ OFFLOAD,
+ HW_ACCELERATOR
+} eff_mode_t;
#define OFFLOAD_PRESET_START_OFFSET_FOR_OPENSL 19
const int map_eq_opensl_preset_2_offload_preset[] = {
@@ -71,35 +99,35 @@
};
int offload_update_mixer_and_effects_ctl(int card, int device_id,
- struct mixer *mixer,
- struct mixer_ctl *ctl)
+ struct mixer **mixer,
+ struct mixer_ctl **ctl)
{
char mixer_string[128];
snprintf(mixer_string, sizeof(mixer_string),
"%s %d", "Audio Effects Config", device_id);
ALOGV("%s: mixer_string: %s", __func__, mixer_string);
- mixer = mixer_open(card);
- if (!mixer) {
+ *mixer = mixer_open(card);
+ if (!(*mixer)) {
ALOGE("Failed to open mixer");
ctl = NULL;
return -EINVAL;
} else {
- ctl = mixer_get_ctl_by_name(mixer, mixer_string);
+ *ctl = mixer_get_ctl_by_name(*mixer, mixer_string);
if (!ctl) {
ALOGE("mixer_get_ctl_by_name failed");
- mixer_close(mixer);
- mixer = NULL;
+ mixer_close(*mixer);
+ *mixer = NULL;
return -EINVAL;
}
}
- ALOGV("mixer: %p, ctl: %p", mixer, ctl);
+ ALOGV("mixer: %p, ctl: %p", *mixer, *ctl);
return 0;
}
-void offload_close_mixer(struct mixer *mixer)
+void offload_close_mixer(struct mixer **mixer)
{
- mixer_close(mixer);
+ mixer_close(*mixer);
}
void offload_bassboost_set_device(struct bass_boost_params *bassboost,
@@ -114,6 +142,10 @@
{
ALOGVV("%s: enable=%d", __func__, (int)enable);
bassboost->enable_flag = enable;
+
+#ifdef DTS_EAGLE
+ update_effects_node(PCM_DEV_ID, EFFECT_TYPE_BB, EFFECT_ENABLE_PARAM, enable, EFFECT_NO_OP, EFFECT_NO_OP, EFFECT_NO_OP);
+#endif
}
int offload_bassboost_get_enable_flag(struct bass_boost_params *bassboost)
@@ -127,6 +159,10 @@
{
ALOGVV("%s: strength %d", __func__, strength);
bassboost->strength = strength;
+
+#ifdef DTS_EAGLE
+ update_effects_node(PCM_DEV_ID, EFFECT_TYPE_BB, EFFECT_SET_PARAM, EFFECT_NO_OP, strength, EFFECT_NO_OP, EFFECT_NO_OP);
+#endif
}
void offload_bassboost_set_mode(struct bass_boost_params *bassboost,
@@ -136,23 +172,23 @@
bassboost->mode = mode;
}
-int offload_bassboost_send_params(struct mixer_ctl *ctl,
- struct bass_boost_params bassboost,
- unsigned param_send_flags)
+static int bassboost_send_params(eff_mode_t mode, void *ctl,
+ struct bass_boost_params *bassboost,
+ unsigned param_send_flags)
{
int param_values[128] = {0};
int *p_param_values = param_values;
ALOGV("%s: flags 0x%x", __func__, param_send_flags);
*p_param_values++ = BASS_BOOST_MODULE;
- *p_param_values++ = bassboost.device;
+ *p_param_values++ = bassboost->device;
*p_param_values++ = 0; /* num of commands*/
if (param_send_flags & OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG) {
*p_param_values++ = BASS_BOOST_ENABLE;
*p_param_values++ = CONFIG_SET;
*p_param_values++ = 0; /* start offset if param size if greater than 128 */
*p_param_values++ = BASS_BOOST_ENABLE_PARAM_LEN;
- *p_param_values++ = bassboost.enable_flag;
+ *p_param_values++ = bassboost->enable_flag;
param_values[2] += 1;
}
if (param_send_flags & OFFLOAD_SEND_BASSBOOST_STRENGTH) {
@@ -160,7 +196,7 @@
*p_param_values++ = CONFIG_SET;
*p_param_values++ = 0; /* start offset if param size if greater than 128 */
*p_param_values++ = BASS_BOOST_STRENGTH_PARAM_LEN;
- *p_param_values++ = bassboost.strength;
+ *p_param_values++ = bassboost->strength;
param_values[2] += 1;
}
if (param_send_flags & OFFLOAD_SEND_BASSBOOST_MODE) {
@@ -168,16 +204,37 @@
*p_param_values++ = CONFIG_SET;
*p_param_values++ = 0; /* start offset if param size if greater than 128 */
*p_param_values++ = BASS_BOOST_MODE_PARAM_LEN;
- *p_param_values++ = bassboost.mode;
+ *p_param_values++ = bassboost->mode;
param_values[2] += 1;
}
- if (param_values[2] && ctl)
- mixer_ctl_set_array(ctl, param_values, ARRAY_SIZE(param_values));
+ if ((mode == OFFLOAD) && param_values[2] && ctl) {
+ mixer_ctl_set_array((struct mixer_ctl *)ctl, param_values,
+ ARRAY_SIZE(param_values));
+ } else if ((mode == HW_ACCELERATOR) && param_values[2] &&
+ ctl && *(int *)ctl) {
+ if (ioctl(*(int *)ctl, AUDIO_EFFECTS_SET_PP_PARAMS, param_values) < 0)
+ ALOGE("%s: sending h/w acc effects params fail[%d]", __func__, errno);
+ }
return 0;
}
+int offload_bassboost_send_params(struct mixer_ctl *ctl,
+ struct bass_boost_params *bassboost,
+ unsigned param_send_flags)
+{
+ return bassboost_send_params(OFFLOAD, (void *)ctl, bassboost,
+ param_send_flags);
+}
+
+int hw_acc_bassboost_send_params(int fd, struct bass_boost_params *bassboost,
+ unsigned param_send_flags)
+{
+ return bassboost_send_params(HW_ACCELERATOR, (void *)&fd,
+ bassboost, param_send_flags);
+}
+
void offload_virtualizer_set_device(struct virtualizer_params *virtualizer,
uint32_t device)
{
@@ -190,6 +247,10 @@
{
ALOGVV("%s: enable=%d", __func__, (int)enable);
virtualizer->enable_flag = enable;
+
+#ifdef DTS_EAGLE
+ update_effects_node(PCM_DEV_ID, EFFECT_TYPE_VIRT, EFFECT_ENABLE_PARAM, enable, EFFECT_NO_OP, EFFECT_NO_OP, EFFECT_NO_OP);
+#endif
}
int offload_virtualizer_get_enable_flag(struct virtualizer_params *virtualizer)
@@ -203,6 +264,10 @@
{
ALOGVV("%s: strength %d", __func__, strength);
virtualizer->strength = strength;
+
+#ifdef DTS_EAGLE
+ update_effects_node(PCM_DEV_ID, EFFECT_TYPE_VIRT, EFFECT_SET_PARAM, EFFECT_NO_OP, strength, EFFECT_NO_OP, EFFECT_NO_OP);
+#endif
}
void offload_virtualizer_set_out_type(struct virtualizer_params *virtualizer,
@@ -219,23 +284,23 @@
virtualizer->gain_adjust = gain_adjust;
}
-int offload_virtualizer_send_params(struct mixer_ctl *ctl,
- struct virtualizer_params virtualizer,
- unsigned param_send_flags)
+static int virtualizer_send_params(eff_mode_t mode, void *ctl,
+ struct virtualizer_params *virtualizer,
+ unsigned param_send_flags)
{
int param_values[128] = {0};
int *p_param_values = param_values;
ALOGV("%s: flags 0x%x", __func__, param_send_flags);
*p_param_values++ = VIRTUALIZER_MODULE;
- *p_param_values++ = virtualizer.device;
+ *p_param_values++ = virtualizer->device;
*p_param_values++ = 0; /* num of commands*/
if (param_send_flags & OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG) {
*p_param_values++ = VIRTUALIZER_ENABLE;
*p_param_values++ = CONFIG_SET;
*p_param_values++ = 0; /* start offset if param size if greater than 128 */
*p_param_values++ = VIRTUALIZER_ENABLE_PARAM_LEN;
- *p_param_values++ = virtualizer.enable_flag;
+ *p_param_values++ = virtualizer->enable_flag;
param_values[2] += 1;
}
if (param_send_flags & OFFLOAD_SEND_VIRTUALIZER_STRENGTH) {
@@ -243,7 +308,7 @@
*p_param_values++ = CONFIG_SET;
*p_param_values++ = 0; /* start offset if param size if greater than 128 */
*p_param_values++ = VIRTUALIZER_STRENGTH_PARAM_LEN;
- *p_param_values++ = virtualizer.strength;
+ *p_param_values++ = virtualizer->strength;
param_values[2] += 1;
}
if (param_send_flags & OFFLOAD_SEND_VIRTUALIZER_OUT_TYPE) {
@@ -251,7 +316,7 @@
*p_param_values++ = CONFIG_SET;
*p_param_values++ = 0; /* start offset if param size if greater than 128 */
*p_param_values++ = VIRTUALIZER_OUT_TYPE_PARAM_LEN;
- *p_param_values++ = virtualizer.out_type;
+ *p_param_values++ = virtualizer->out_type;
param_values[2] += 1;
}
if (param_send_flags & OFFLOAD_SEND_VIRTUALIZER_GAIN_ADJUST) {
@@ -259,16 +324,38 @@
*p_param_values++ = CONFIG_SET;
*p_param_values++ = 0; /* start offset if param size if greater than 128 */
*p_param_values++ = VIRTUALIZER_GAIN_ADJUST_PARAM_LEN;
- *p_param_values++ = virtualizer.gain_adjust;
+ *p_param_values++ = virtualizer->gain_adjust;
param_values[2] += 1;
}
- if (param_values[2] && ctl)
- mixer_ctl_set_array(ctl, param_values, ARRAY_SIZE(param_values));
+ if ((mode == OFFLOAD) && param_values[2] && ctl) {
+ mixer_ctl_set_array((struct mixer_ctl *)ctl, param_values,
+ ARRAY_SIZE(param_values));
+ } else if ((mode == HW_ACCELERATOR) && param_values[2] &&
+ ctl && *(int *)ctl) {
+ if (ioctl(*(int *)ctl, AUDIO_EFFECTS_SET_PP_PARAMS, param_values) < 0)
+ ALOGE("%s: sending h/w acc effects params fail[%d]", __func__, errno);
+ }
return 0;
}
+int offload_virtualizer_send_params(struct mixer_ctl *ctl,
+ struct virtualizer_params *virtualizer,
+ unsigned param_send_flags)
+{
+ return virtualizer_send_params(OFFLOAD, (void *)ctl, virtualizer,
+ param_send_flags);
+}
+
+int hw_acc_virtualizer_send_params(int fd,
+ struct virtualizer_params *virtualizer,
+ unsigned param_send_flags)
+{
+ return virtualizer_send_params(HW_ACCELERATOR, (void *)&fd,
+ virtualizer, param_send_flags);
+}
+
void offload_eq_set_device(struct eq_params *eq, uint32_t device)
{
ALOGVV("%s: device 0x%x", __func__, device);
@@ -279,6 +366,10 @@
{
ALOGVV("%s: enable=%d", __func__, (int)enable);
eq->enable_flag = enable;
+
+#ifdef DTS_EAGLE
+ update_effects_node(PCM_DEV_ID, EFFECT_TYPE_EQ, EFFECT_ENABLE_PARAM, enable, EFFECT_NO_OP, EFFECT_NO_OP, EFFECT_NO_OP);
+#endif
}
int offload_eq_get_enable_flag(struct eq_params *eq)
@@ -308,30 +399,34 @@
eq->per_band_cfg[i].gain_millibels = band_gain_list[i] * 100;
eq->per_band_cfg[i].quality_factor = Q8_UNITY;
}
+
+#ifdef DTS_EAGLE
+ update_effects_node(PCM_DEV_ID, EFFECT_TYPE_EQ, EFFECT_SET_PARAM, EFFECT_NO_OP, EFFECT_NO_OP, i, band_gain_list[i] * 100);
+#endif
}
-int offload_eq_send_params(struct mixer_ctl *ctl, struct eq_params eq,
- unsigned param_send_flags)
+static int eq_send_params(eff_mode_t mode, void *ctl, struct eq_params *eq,
+ unsigned param_send_flags)
{
int param_values[128] = {0};
int *p_param_values = param_values;
uint32_t i;
ALOGV("%s: flags 0x%x", __func__, param_send_flags);
- if ((eq.config.preset_id < -1) ||
- ((param_send_flags & OFFLOAD_SEND_EQ_PRESET) && (eq.config.preset_id == -1))) {
+ if ((eq->config.preset_id < -1) ||
+ ((param_send_flags & OFFLOAD_SEND_EQ_PRESET) && (eq->config.preset_id == -1))) {
ALOGV("No Valid preset to set");
return 0;
}
*p_param_values++ = EQ_MODULE;
- *p_param_values++ = eq.device;
+ *p_param_values++ = eq->device;
*p_param_values++ = 0; /* num of commands*/
if (param_send_flags & OFFLOAD_SEND_EQ_ENABLE_FLAG) {
*p_param_values++ = EQ_ENABLE;
*p_param_values++ = CONFIG_SET;
*p_param_values++ = 0; /* start offset if param size if greater than 128 */
*p_param_values++ = EQ_ENABLE_PARAM_LEN;
- *p_param_values++ = eq.enable_flag;
+ *p_param_values++ = eq->enable_flag;
param_values[2] += 1;
}
if (param_send_flags & OFFLOAD_SEND_EQ_PRESET) {
@@ -339,9 +434,9 @@
*p_param_values++ = CONFIG_SET;
*p_param_values++ = 0; /* start offset if param size if greater than 128 */
*p_param_values++ = EQ_CONFIG_PARAM_LEN;
- *p_param_values++ = eq.config.eq_pregain;
+ *p_param_values++ = eq->config.eq_pregain;
*p_param_values++ =
- map_eq_opensl_preset_2_offload_preset[eq.config.preset_id];
+ map_eq_opensl_preset_2_offload_preset[eq->config.preset_id];
*p_param_values++ = 0;
param_values[2] += 1;
}
@@ -350,26 +445,45 @@
*p_param_values++ = CONFIG_SET;
*p_param_values++ = 0; /* start offset if param size if greater than 128 */
*p_param_values++ = EQ_CONFIG_PARAM_LEN +
- eq.config.num_bands * EQ_CONFIG_PER_BAND_PARAM_LEN;
- *p_param_values++ = eq.config.eq_pregain;
+ eq->config.num_bands * EQ_CONFIG_PER_BAND_PARAM_LEN;
+ *p_param_values++ = eq->config.eq_pregain;
*p_param_values++ = CUSTOM_OPENSL_PRESET;
- *p_param_values++ = eq.config.num_bands;
- for (i=0; i<eq.config.num_bands; i++) {
- *p_param_values++ = eq.per_band_cfg[i].band_idx;
- *p_param_values++ = eq.per_band_cfg[i].filter_type;
- *p_param_values++ = eq.per_band_cfg[i].freq_millihertz;
- *p_param_values++ = eq.per_band_cfg[i].gain_millibels;
- *p_param_values++ = eq.per_band_cfg[i].quality_factor;
+ *p_param_values++ = eq->config.num_bands;
+ for (i=0; i<eq->config.num_bands; i++) {
+ *p_param_values++ = eq->per_band_cfg[i].band_idx;
+ *p_param_values++ = eq->per_band_cfg[i].filter_type;
+ *p_param_values++ = eq->per_band_cfg[i].freq_millihertz;
+ *p_param_values++ = eq->per_band_cfg[i].gain_millibels;
+ *p_param_values++ = eq->per_band_cfg[i].quality_factor;
}
param_values[2] += 1;
}
- if (param_values[2] && ctl)
- mixer_ctl_set_array(ctl, param_values, ARRAY_SIZE(param_values));
+ if ((mode == OFFLOAD) && param_values[2] && ctl) {
+ mixer_ctl_set_array((struct mixer_ctl *)ctl, param_values,
+ ARRAY_SIZE(param_values));
+ } else if ((mode == HW_ACCELERATOR) && param_values[2] &&
+ ctl && *(int *)ctl) {
+ if (ioctl(*(int *)ctl, AUDIO_EFFECTS_SET_PP_PARAMS, param_values) < 0)
+ ALOGE("%s: sending h/w acc effects params fail[%d]", __func__, errno);
+ }
return 0;
}
+int offload_eq_send_params(struct mixer_ctl *ctl, struct eq_params *eq,
+ unsigned param_send_flags)
+{
+ return eq_send_params(OFFLOAD, (void *)ctl, eq, param_send_flags);
+}
+
+int hw_acc_eq_send_params(int fd, struct eq_params *eq,
+ unsigned param_send_flags)
+{
+ return eq_send_params(HW_ACCELERATOR, (void *)&fd, eq,
+ param_send_flags);
+}
+
void offload_reverb_set_device(struct reverb_params *reverb, uint32_t device)
{
ALOGVV("%s: device 0x%x", __func__, device);
@@ -479,16 +593,16 @@
reverb->density = density;
}
-int offload_reverb_send_params(struct mixer_ctl *ctl,
- struct reverb_params reverb,
- unsigned param_send_flags)
+static int reverb_send_params(eff_mode_t mode, void *ctl,
+ struct reverb_params *reverb,
+ unsigned param_send_flags)
{
int param_values[128] = {0};
int *p_param_values = param_values;
ALOGV("%s: flags 0x%x", __func__, param_send_flags);
*p_param_values++ = REVERB_MODULE;
- *p_param_values++ = reverb.device;
+ *p_param_values++ = reverb->device;
*p_param_values++ = 0; /* num of commands*/
if (param_send_flags & OFFLOAD_SEND_REVERB_ENABLE_FLAG) {
@@ -496,7 +610,7 @@
*p_param_values++ = CONFIG_SET;
*p_param_values++ = 0; /* start offset if param size if greater than 128 */
*p_param_values++ = REVERB_ENABLE_PARAM_LEN;
- *p_param_values++ = reverb.enable_flag;
+ *p_param_values++ = reverb->enable_flag;
param_values[2] += 1;
}
if (param_send_flags & OFFLOAD_SEND_REVERB_MODE) {
@@ -504,7 +618,7 @@
*p_param_values++ = CONFIG_SET;
*p_param_values++ = 0; /* start offset if param size if greater than 128 */
*p_param_values++ = REVERB_MODE_PARAM_LEN;
- *p_param_values++ = reverb.mode;
+ *p_param_values++ = reverb->mode;
param_values[2] += 1;
}
if (param_send_flags & OFFLOAD_SEND_REVERB_PRESET) {
@@ -512,7 +626,7 @@
*p_param_values++ = CONFIG_SET;
*p_param_values++ = 0; /* start offset if param size if greater than 128 */
*p_param_values++ = REVERB_PRESET_PARAM_LEN;
- *p_param_values++ = reverb.preset;
+ *p_param_values++ = reverb->preset;
param_values[2] += 1;
}
if (param_send_flags & OFFLOAD_SEND_REVERB_WET_MIX) {
@@ -520,7 +634,7 @@
*p_param_values++ = CONFIG_SET;
*p_param_values++ = 0; /* start offset if param size if greater than 128 */
*p_param_values++ = REVERB_WET_MIX_PARAM_LEN;
- *p_param_values++ = reverb.wet_mix;
+ *p_param_values++ = reverb->wet_mix;
param_values[2] += 1;
}
if (param_send_flags & OFFLOAD_SEND_REVERB_GAIN_ADJUST) {
@@ -528,7 +642,7 @@
*p_param_values++ = CONFIG_SET;
*p_param_values++ = 0; /* start offset if param size if greater than 128 */
*p_param_values++ = REVERB_GAIN_ADJUST_PARAM_LEN;
- *p_param_values++ = reverb.gain_adjust;
+ *p_param_values++ = reverb->gain_adjust;
param_values[2] += 1;
}
if (param_send_flags & OFFLOAD_SEND_REVERB_ROOM_LEVEL) {
@@ -536,7 +650,7 @@
*p_param_values++ = CONFIG_SET;
*p_param_values++ = 0; /* start offset if param size if greater than 128 */
*p_param_values++ = REVERB_ROOM_LEVEL_PARAM_LEN;
- *p_param_values++ = reverb.room_level;
+ *p_param_values++ = reverb->room_level;
param_values[2] += 1;
}
if (param_send_flags & OFFLOAD_SEND_REVERB_ROOM_HF_LEVEL) {
@@ -544,7 +658,7 @@
*p_param_values++ = CONFIG_SET;
*p_param_values++ = 0; /* start offset if param size if greater than 128 */
*p_param_values++ = REVERB_ROOM_HF_LEVEL_PARAM_LEN;
- *p_param_values++ = reverb.room_hf_level;
+ *p_param_values++ = reverb->room_hf_level;
param_values[2] += 1;
}
if (param_send_flags & OFFLOAD_SEND_REVERB_DECAY_TIME) {
@@ -552,7 +666,7 @@
*p_param_values++ = CONFIG_SET;
*p_param_values++ = 0; /* start offset if param size if greater than 128 */
*p_param_values++ = REVERB_DECAY_TIME_PARAM_LEN;
- *p_param_values++ = reverb.decay_time;
+ *p_param_values++ = reverb->decay_time;
param_values[2] += 1;
}
if (param_send_flags & OFFLOAD_SEND_REVERB_DECAY_HF_RATIO) {
@@ -560,7 +674,7 @@
*p_param_values++ = CONFIG_SET;
*p_param_values++ = 0; /* start offset if param size if greater than 128 */
*p_param_values++ = REVERB_DECAY_HF_RATIO_PARAM_LEN;
- *p_param_values++ = reverb.decay_hf_ratio;
+ *p_param_values++ = reverb->decay_hf_ratio;
param_values[2] += 1;
}
if (param_send_flags & OFFLOAD_SEND_REVERB_REFLECTIONS_LEVEL) {
@@ -568,7 +682,7 @@
*p_param_values++ = CONFIG_SET;
*p_param_values++ = 0; /* start offset if param size if greater than 128 */
*p_param_values++ = REVERB_REFLECTIONS_LEVEL_PARAM_LEN;
- *p_param_values++ = reverb.reflections_level;
+ *p_param_values++ = reverb->reflections_level;
param_values[2] += 1;
}
if (param_send_flags & OFFLOAD_SEND_REVERB_REFLECTIONS_DELAY) {
@@ -576,7 +690,7 @@
*p_param_values++ = CONFIG_SET;
*p_param_values++ = 0; /* start offset if param size if greater than 128 */
*p_param_values++ = REVERB_REFLECTIONS_DELAY_PARAM_LEN;
- *p_param_values++ = reverb.reflections_delay;
+ *p_param_values++ = reverb->reflections_delay;
param_values[2] += 1;
}
if (param_send_flags & OFFLOAD_SEND_REVERB_LEVEL) {
@@ -584,7 +698,7 @@
*p_param_values++ = CONFIG_SET;
*p_param_values++ = 0; /* start offset if param size if greater than 128 */
*p_param_values++ = REVERB_LEVEL_PARAM_LEN;
- *p_param_values++ = reverb.level;
+ *p_param_values++ = reverb->level;
param_values[2] += 1;
}
if (param_send_flags & OFFLOAD_SEND_REVERB_DELAY) {
@@ -592,7 +706,7 @@
*p_param_values++ = CONFIG_SET;
*p_param_values++ = 0; /* start offset if param size if greater than 128 */
*p_param_values++ = REVERB_DELAY_PARAM_LEN;
- *p_param_values++ = reverb.delay;
+ *p_param_values++ = reverb->delay;
param_values[2] += 1;
}
if (param_send_flags & OFFLOAD_SEND_REVERB_DIFFUSION) {
@@ -600,7 +714,7 @@
*p_param_values++ = CONFIG_SET;
*p_param_values++ = 0; /* start offset if param size if greater than 128 */
*p_param_values++ = REVERB_DIFFUSION_PARAM_LEN;
- *p_param_values++ = reverb.diffusion;
+ *p_param_values++ = reverb->diffusion;
param_values[2] += 1;
}
if (param_send_flags & OFFLOAD_SEND_REVERB_DENSITY) {
@@ -608,7 +722,92 @@
*p_param_values++ = CONFIG_SET;
*p_param_values++ = 0; /* start offset if param size if greater than 128 */
*p_param_values++ = REVERB_DENSITY_PARAM_LEN;
- *p_param_values++ = reverb.density;
+ *p_param_values++ = reverb->density;
+ param_values[2] += 1;
+ }
+
+ if ((mode == OFFLOAD) && param_values[2] && ctl) {
+ mixer_ctl_set_array((struct mixer_ctl *)ctl, param_values,
+ ARRAY_SIZE(param_values));
+ } else if ((mode == HW_ACCELERATOR) && param_values[2] &&
+ ctl && *(int *)ctl) {
+ if (ioctl(*(int *)ctl, AUDIO_EFFECTS_SET_PP_PARAMS, param_values) < 0)
+ ALOGE("%s: sending h/w acc effects params fail[%d]", __func__, errno);
+ }
+
+ return 0;
+}
+
+int offload_reverb_send_params(struct mixer_ctl *ctl,
+ struct reverb_params *reverb,
+ unsigned param_send_flags)
+{
+ return reverb_send_params(OFFLOAD, (void *)ctl, reverb,
+ param_send_flags);
+}
+
+int hw_acc_reverb_send_params(int fd, struct reverb_params *reverb,
+ unsigned param_send_flags)
+{
+ return reverb_send_params(HW_ACCELERATOR, (void *)&fd,
+ reverb, param_send_flags);
+}
+
+void offload_soft_volume_set_enable(struct soft_volume_params *vol, bool enable)
+{
+ ALOGV("%s", __func__);
+ vol->enable_flag = enable;
+}
+
+void offload_soft_volume_set_gain_master(struct soft_volume_params *vol, int gain)
+{
+ ALOGV("%s", __func__);
+ vol->master_gain = gain;
+}
+
+void offload_soft_volume_set_gain_2ch(struct soft_volume_params *vol,
+ int l_gain, int r_gain)
+{
+ ALOGV("%s", __func__);
+ vol->left_gain = l_gain;
+ vol->right_gain = r_gain;
+}
+
+int offload_soft_volume_send_params(struct mixer_ctl *ctl,
+ struct soft_volume_params vol,
+ unsigned param_send_flags)
+{
+ int param_values[128] = {0};
+ int *p_param_values = param_values;
+ uint32_t i;
+
+ ALOGV("%s", __func__);
+ *p_param_values++ = SOFT_VOLUME_MODULE;
+ *p_param_values++ = 0;
+ *p_param_values++ = 0; /* num of commands*/
+ if (param_send_flags & OFFLOAD_SEND_SOFT_VOLUME_ENABLE_FLAG) {
+ *p_param_values++ = SOFT_VOLUME_ENABLE;
+ *p_param_values++ = CONFIG_SET;
+ *p_param_values++ = 0; /* start offset if param size if greater than 128 */
+ *p_param_values++ = SOFT_VOLUME_ENABLE_PARAM_LEN;
+ *p_param_values++ = vol.enable_flag;
+ param_values[2] += 1;
+ }
+ if (param_send_flags & OFFLOAD_SEND_SOFT_VOLUME_GAIN_MASTER) {
+ *p_param_values++ = SOFT_VOLUME_GAIN_MASTER;
+ *p_param_values++ = CONFIG_SET;
+ *p_param_values++ = 0; /* start offset if param size if greater than 128 */
+ *p_param_values++ = SOFT_VOLUME_GAIN_MASTER_PARAM_LEN;
+ *p_param_values++ = vol.master_gain;
+ param_values[2] += 1;
+ }
+ if (param_send_flags & OFFLOAD_SEND_SOFT_VOLUME_GAIN_2CH) {
+ *p_param_values++ = SOFT_VOLUME_GAIN_2CH;
+ *p_param_values++ = CONFIG_SET;
+ *p_param_values++ = 0; /* start offset if param size if greater than 128 */
+ *p_param_values++ = SOFT_VOLUME_GAIN_2CH_PARAM_LEN;
+ *p_param_values++ = vol.left_gain;
+ *p_param_values++ = vol.right_gain;
param_values[2] += 1;
}
@@ -617,3 +816,104 @@
return 0;
}
+
+void offload_transition_soft_volume_set_enable(struct soft_volume_params *vol,
+ bool enable)
+{
+ ALOGV("%s", __func__);
+ vol->enable_flag = enable;
+}
+
+void offload_transition_soft_volume_set_gain_master(struct soft_volume_params *vol,
+ int gain)
+{
+ ALOGV("%s", __func__);
+ vol->master_gain = gain;
+}
+
+void offload_transition_soft_volume_set_gain_2ch(struct soft_volume_params *vol,
+ int l_gain, int r_gain)
+{
+ ALOGV("%s", __func__);
+ vol->left_gain = l_gain;
+ vol->right_gain = r_gain;
+}
+
+int offload_transition_soft_volume_send_params(struct mixer_ctl *ctl,
+ struct soft_volume_params vol,
+ unsigned param_send_flags)
+{
+ int param_values[128] = {0};
+ int *p_param_values = param_values;
+ uint32_t i;
+
+ ALOGV("%s", __func__);
+ *p_param_values++ = SOFT_VOLUME2_MODULE;
+ *p_param_values++ = 0;
+ *p_param_values++ = 0; /* num of commands*/
+ if (param_send_flags & OFFLOAD_SEND_TRANSITION_SOFT_VOLUME_ENABLE_FLAG) {
+ *p_param_values++ = SOFT_VOLUME2_ENABLE;
+ *p_param_values++ = CONFIG_SET;
+ *p_param_values++ = 0; /* start offset if param size if greater than 128 */
+ *p_param_values++ = SOFT_VOLUME2_ENABLE_PARAM_LEN;
+ *p_param_values++ = vol.enable_flag;
+ param_values[2] += 1;
+ }
+ if (param_send_flags & OFFLOAD_SEND_TRANSITION_SOFT_VOLUME_GAIN_MASTER) {
+ *p_param_values++ = SOFT_VOLUME2_GAIN_MASTER;
+ *p_param_values++ = CONFIG_SET;
+ *p_param_values++ = 0; /* start offset if param size if greater than 128 */
+ *p_param_values++ = SOFT_VOLUME2_GAIN_MASTER_PARAM_LEN;
+ *p_param_values++ = vol.master_gain;
+ param_values[2] += 1;
+ }
+ if (param_send_flags & OFFLOAD_SEND_TRANSITION_SOFT_VOLUME_GAIN_2CH) {
+ *p_param_values++ = SOFT_VOLUME2_GAIN_2CH;
+ *p_param_values++ = CONFIG_SET;
+ *p_param_values++ = 0; /* start offset if param size if greater than 128 */
+ *p_param_values++ = SOFT_VOLUME2_GAIN_2CH_PARAM_LEN;
+ *p_param_values++ = vol.left_gain;
+ *p_param_values++ = vol.right_gain;
+ param_values[2] += 1;
+ }
+
+ if (param_values[2] && ctl)
+ mixer_ctl_set_array(ctl, param_values, ARRAY_SIZE(param_values));
+
+ return 0;
+}
+
+static int hpx_send_params(eff_mode_t mode, void *ctl,
+ unsigned param_send_flags)
+{
+ int param_values[128] = {0};
+ int *p_param_values = param_values;
+ uint32_t i;
+
+ ALOGV("%s", __func__);
+ if (param_send_flags & OFFLOAD_SEND_HPX_STATE_OFF) {
+ *p_param_values++ = DTS_EAGLE_MODULE_ENABLE;
+ *p_param_values++ = 0; /* hpx off*/
+ } else if (param_send_flags & OFFLOAD_SEND_HPX_STATE_ON) {
+ *p_param_values++ = DTS_EAGLE_MODULE_ENABLE;
+ *p_param_values++ = 1; /* hpx on*/
+ }
+
+ if ((mode == OFFLOAD) && ctl)
+ mixer_ctl_set_array(ctl, param_values, ARRAY_SIZE(param_values));
+ else {
+ if (ioctl(*(int *)ctl, AUDIO_EFFECTS_SET_PP_PARAMS, param_values) < 0)
+ ALOGE("%s: sending h/w acc hpx state params fail[%d]", __func__, errno);
+ }
+ return 0;
+}
+
+int offload_hpx_send_params(struct mixer_ctl *ctl, unsigned param_send_flags)
+{
+ return hpx_send_params(OFFLOAD, (void *)ctl, param_send_flags);
+}
+
+int hw_acc_hpx_send_params(int fd, unsigned param_send_flags)
+{
+ return hpx_send_params(HW_ACCELERATOR, (void *)&fd, param_send_flags);
+}
diff --git a/post_proc/effect_api.h b/post_proc/effect_api.h
index 342c606..e05924a 100644
--- a/post_proc/effect_api.h
+++ b/post_proc/effect_api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, 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
@@ -30,10 +30,14 @@
#ifndef OFFLOAD_EFFECT_API_H_
#define OFFLOAD_EFFECT_API_H_
+#if __cplusplus
+extern "C" {
+#endif
+
int offload_update_mixer_and_effects_ctl(int card, int device_id,
- struct mixer *mixer,
- struct mixer_ctl *ctl);
-void offload_close_mixer(struct mixer *mixer);
+ struct mixer **mixer,
+ struct mixer_ctl **ctl);
+void offload_close_mixer(struct mixer **mixer);
#define OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG (1 << 0)
#define OFFLOAD_SEND_BASSBOOST_STRENGTH \
@@ -50,8 +54,11 @@
void offload_bassboost_set_mode(struct bass_boost_params *bassboost,
int mode);
int offload_bassboost_send_params(struct mixer_ctl *ctl,
- struct bass_boost_params bassboost,
+ struct bass_boost_params *bassboost,
unsigned param_send_flags);
+int hw_acc_bassboost_send_params(int fd,
+ struct bass_boost_params *bassboost,
+ unsigned param_send_flags);
#define OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG (1 << 0)
#define OFFLOAD_SEND_VIRTUALIZER_STRENGTH \
@@ -72,8 +79,11 @@
void offload_virtualizer_set_gain_adjust(struct virtualizer_params *virtualizer,
int gain_adjust);
int offload_virtualizer_send_params(struct mixer_ctl *ctl,
- struct virtualizer_params virtualizer,
+ struct virtualizer_params *virtualizer,
unsigned param_send_flags);
+int hw_acc_virtualizer_send_params(int fd,
+ struct virtualizer_params *virtualizer,
+ unsigned param_send_flags);
#define OFFLOAD_SEND_EQ_ENABLE_FLAG (1 << 0)
#define OFFLOAD_SEND_EQ_PRESET \
@@ -87,8 +97,10 @@
void offload_eq_set_bands_level(struct eq_params *eq, int num_bands,
const uint16_t *band_freq_list,
int *band_gain_list);
-int offload_eq_send_params(struct mixer_ctl *ctl, struct eq_params eq,
+int offload_eq_send_params(struct mixer_ctl *ctl, struct eq_params *eq,
unsigned param_send_flags);
+int hw_acc_eq_send_params(int fd, struct eq_params *eq,
+ unsigned param_send_flags);
#define OFFLOAD_SEND_REVERB_ENABLE_FLAG (1 << 0)
#define OFFLOAD_SEND_REVERB_MODE \
@@ -145,7 +157,49 @@
void offload_reverb_set_diffusion(struct reverb_params *reverb, int diffusion);
void offload_reverb_set_density(struct reverb_params *reverb, int density);
int offload_reverb_send_params(struct mixer_ctl *ctl,
- struct reverb_params reverb,
+ struct reverb_params *reverb,
unsigned param_send_flags);
+int hw_acc_reverb_send_params(int fd,
+ struct reverb_params *reverb,
+ unsigned param_send_flags);
+
+#define OFFLOAD_SEND_SOFT_VOLUME_ENABLE_FLAG (1 << 0)
+#define OFFLOAD_SEND_SOFT_VOLUME_GAIN_2CH \
+ (OFFLOAD_SEND_SOFT_VOLUME_ENABLE_FLAG << 1)
+#define OFFLOAD_SEND_SOFT_VOLUME_GAIN_MASTER \
+ (OFFLOAD_SEND_SOFT_VOLUME_GAIN_2CH << 1)
+void offload_soft_volume_set_enable(struct soft_volume_params *vol,
+ bool enable);
+void offload_soft_volume_set_gain_master(struct soft_volume_params *vol,
+ int gain);
+void offload_soft_volume_set_gain_2ch(struct soft_volume_params *vol,
+ int l_gain, int r_gain);
+int offload_soft_volume_send_params(struct mixer_ctl *ctl,
+ struct soft_volume_params vol,
+ unsigned param_send_flags);
+
+#define OFFLOAD_SEND_TRANSITION_SOFT_VOLUME_ENABLE_FLAG (1 << 0)
+#define OFFLOAD_SEND_TRANSITION_SOFT_VOLUME_GAIN_2CH \
+ (OFFLOAD_SEND_TRANSITION_SOFT_VOLUME_ENABLE_FLAG << 1)
+#define OFFLOAD_SEND_TRANSITION_SOFT_VOLUME_GAIN_MASTER \
+ (OFFLOAD_SEND_TRANSITION_SOFT_VOLUME_GAIN_2CH << 1)
+void offload_transition_soft_volume_set_enable(struct soft_volume_params *vol,
+ bool enable);
+void offload_transition_soft_volume_set_gain_master(struct soft_volume_params *vol,
+ int gain);
+void offload_transition_soft_volume_set_gain_2ch(struct soft_volume_params *vol,
+ int l_gain, int r_gain);
+int offload_transition_soft_volume_send_params(struct mixer_ctl *ctl,
+ struct soft_volume_params vol,
+ unsigned param_send_flags);
+
+#define OFFLOAD_SEND_HPX_STATE_ON (1 << 0)
+#define OFFLOAD_SEND_HPX_STATE_OFF (OFFLOAD_SEND_HPX_STATE_ON << 1)
+int offload_hpx_send_params(struct mixer_ctl *ctl, unsigned param_send_flags);
+int hw_acc_hpx_send_params(int fd, unsigned param_send_flags);
+
+#if __cplusplus
+} //extern "C"
+#endif
#endif /*OFFLOAD_EFFECT_API_H_*/
diff --git a/post_proc/effect_util.c b/post_proc/effect_util.c
new file mode 100644
index 0000000..cda89bc
--- /dev/null
+++ b/post_proc/effect_util.c
@@ -0,0 +1,210 @@
+/*
+ * (C) 2014 DTS, Inc.
+ *
+ * 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.
+ */
+
+#include <utils/Log.h>
+#include <stdlib.h>
+#include "effect_util.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "effect_util"
+
+/*#define LOG_NDEBUG 0*/
+
+enum {
+ EQUALIZER,
+ VIRTUALIZER,
+ BASSBOOST,
+};
+
+static const char *paramList[10] = {
+ "eq_enable",
+ "virt_enable",
+ "bb_enable",
+ "eq_param_level0",
+ "eq_param_level1",
+ "eq_param_level2",
+ "eq_param_level3",
+ "eq_param_level4",
+ "virt_param_strength",
+ "bassboost_param_strength"
+};
+
+#define EFFECT_FILE "/data/data/dts/effect"
+#define MAX_LENGTH_OF_INTEGER_IN_STRING 13
+
+#ifdef DTS_EAGLE
+void create_effect_state_node(int device_id)
+{
+ char prop[PROPERTY_VALUE_MAX];
+ int fd;
+ char buf[1024];
+ char path[PATH_MAX];
+ char value[MAX_LENGTH_OF_INTEGER_IN_STRING];
+
+ property_get("use.dts_eagle", prop, "0");
+ if (!strncmp("true", prop, sizeof("true")) || atoi(prop)) {
+ ALOGV("create_effect_node for - device_id: %d", device_id);
+ strlcpy(path, EFFECT_FILE, sizeof(path));
+ snprintf(value, sizeof(value), "%d", device_id);
+ strlcat(path, value, sizeof(path));
+ if ((fd=open(path, O_RDONLY)) < 0) {
+ ALOGV("No File exist");
+ } else {
+ ALOGV("A file with the same name exist. So, not creating again");
+ return;
+ }
+ if ((fd=creat(path, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) {
+ ALOGE("opening effect state node failed returned");
+ return;
+ }
+ chmod(path, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH);
+ snprintf(buf, sizeof(buf), "eq_enable=%d;virt_enable=%d;bb_enable=%d;eq_param_level0=%d;eq_param_level1=%d;eq_param_level2=%d;eq_param_level3=%d;eq_param_level4=%d;virt_param_strength=%d;bassboost_param_strength=%d", 0,0,0,0,0,0,0,0,0,0);
+ int n = write(fd, buf, strlen(buf));
+ ALOGV("number of bytes written: %d", n);
+ close(fd);
+ }
+}
+
+void update_effects_node(int device_id, int effect_type, int enable_or_set, int enable_disable, int strength, int eq_band, int eq_level)
+{
+ char prop[PROPERTY_VALUE_MAX];
+ char buf[1024];
+ int fd = 0;
+ int paramValue = 0;
+ char path[PATH_MAX];
+ char value[MAX_LENGTH_OF_INTEGER_IN_STRING];
+ char parameterValue[MAX_LENGTH_OF_INTEGER_IN_STRING];
+ int keyParamIndex = -1; //index in the paramlist array which has to be updated
+ char *s1, *s2;
+ char resultBuf[1024];
+ int index1 = -1;
+ //ALOGV("value of device_id and effect_type is %d and %d", device_id, effect_type);
+ property_get("use.dts_eagle", prop, "0");
+ if (!strncmp("true", prop, sizeof("true")) || atoi(prop)) {
+ strlcpy(path, EFFECT_FILE, sizeof(path));
+ snprintf(value, sizeof(value), "%d", device_id);
+ strlcat(path, value, sizeof(path));
+ switch (effect_type)
+ {
+ case EQUALIZER:
+ if (enable_or_set) {
+ keyParamIndex = 0;
+ paramValue = enable_disable;
+ } else {
+ switch (eq_band) {
+ case 0:
+ keyParamIndex = 3;
+ break;
+ case 1:
+ keyParamIndex = 4;
+ break;
+ case 2:
+ keyParamIndex = 5;
+ break;
+ case 3:
+ keyParamIndex = 6;
+ break;
+ case 4:
+ keyParamIndex = 7;
+ break;
+ default:
+ break;
+ }
+ paramValue = eq_level;
+ }
+ break;
+ case VIRTUALIZER:
+ if(enable_or_set) {
+ keyParamIndex = 1;
+ paramValue = enable_disable;
+ } else {
+ keyParamIndex = 8;
+ paramValue = strength;
+ }
+ break;
+ case BASSBOOST:
+ if (enable_or_set) {
+ keyParamIndex = 2;
+ paramValue = enable_disable;
+ } else {
+ keyParamIndex = 9;
+ paramValue = strength;
+ }
+ break;
+ default:
+ break;
+ }
+ if(keyParamIndex !=-1) {
+ FILE *fp;
+ fp = fopen(path,"r");
+ if (fp != NULL) {
+ memset(buf, 0, 1024);
+ memset(resultBuf, 0, 1024);
+ if (fgets(buf, 1024, fp) != NULL) {
+ s1 = strstr(buf, paramList[keyParamIndex]);
+ s2 = strstr(s1,";");
+ index1 = s1 - buf;
+ strncpy(resultBuf, buf, index1);
+ strncat(resultBuf, paramList[keyParamIndex], sizeof(resultBuf)-strlen(resultBuf)-1);
+ strncat(resultBuf, "=", sizeof(resultBuf)-strlen(resultBuf)-1);
+ snprintf(parameterValue, sizeof(parameterValue), "%d", paramValue);
+ strncat(resultBuf, parameterValue, sizeof(resultBuf)-strlen(resultBuf)-1);
+ if (s2)
+ strncat(resultBuf, s2, sizeof(resultBuf)-strlen(resultBuf)-1);
+ fclose(fp);
+ if ((fd=open(path, O_TRUNC|O_WRONLY)) < 0) {
+ ALOGV("opening file for writing failed");
+ return;
+ }
+ int n = write(fd, resultBuf, strlen(resultBuf));
+ close(fd);
+ ALOGV("number of bytes written: %d", n);
+ } else {
+ ALOGV("file could not be read");
+ fclose(fp);
+ }
+ } else
+ ALOGV("file could not be opened");
+ }
+ }
+}
+
+void remove_effect_state_node(int device_id)
+{
+ char prop[PROPERTY_VALUE_MAX];
+ int fd;
+ char path[PATH_MAX];
+ char value[MAX_LENGTH_OF_INTEGER_IN_STRING];
+
+ property_get("use.dts_eagle", prop, "0");
+ if (!strncmp("true", prop, sizeof("true")) || atoi(prop)) {
+ ALOGV("remove_state_notifier_node: device_id - %d", device_id);
+ strlcpy(path, EFFECT_FILE, sizeof(path));
+ snprintf(value, sizeof(value), "%d", device_id);
+ strlcat(path, value, sizeof(path));
+ if ((fd=open(path, O_RDONLY)) < 0) {
+ ALOGV("open effect state node failed");
+ } else {
+ ALOGV("open effect state node successful");
+ ALOGV("Remove the file");
+ close(fd);
+ remove(path);
+ }
+ }
+}
+#endif
diff --git a/post_proc/effect_util.h b/post_proc/effect_util.h
new file mode 100644
index 0000000..38bd9bd
--- /dev/null
+++ b/post_proc/effect_util.h
@@ -0,0 +1,47 @@
+/*
+ * (C) 2014 DTS, Inc.
+ *
+ * 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.
+ */
+
+#ifndef EFFECT_UTIL_H_
+#define EFFECT_UTIL_H_
+
+#ifdef DTS_EAGLE
+
+#include <cutils/properties.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+enum {
+ EFFECT_TYPE_EQ = 0,
+ EFFECT_TYPE_VIRT,
+ EFFECT_TYPE_BB,
+};
+
+enum {
+ EFFECT_SET_PARAM = 0,
+ EFFECT_ENABLE_PARAM,
+};
+
+
+#define EFFECT_NO_OP 0
+#define PCM_DEV_ID 9
+
+void create_effect_state_node(int device_id);
+void update_effects_node(int device_id, int effect_type, int enable_or_set, int enable_disable, int strength, int band, int level);
+void remove_effect_state_node(int device_id);
+
+#endif /*DTS_EAGLE*/
+
+#endif /*EFFECT_UTIL_H_*/
diff --git a/post_proc/equalizer.c b/post_proc/equalizer.c
index 7355ead..c2ae326 100644
--- a/post_proc/equalizer.c
+++ b/post_proc/equalizer.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -18,7 +18,7 @@
*/
#define LOG_TAG "offload_effect_equalizer"
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
#include <cutils/list.h>
#include <cutils/log.h>
@@ -110,9 +110,13 @@
equalizer_band_presets_freq,
context->band_levels);
if (context->ctl)
- offload_eq_send_params(context->ctl, context->offload_eq,
+ offload_eq_send_params(context->ctl, &context->offload_eq,
OFFLOAD_SEND_EQ_ENABLE_FLAG |
OFFLOAD_SEND_EQ_BANDS_LEVEL);
+ if (context->hw_acc_fd > 0)
+ hw_acc_eq_send_params(context->hw_acc_fd, &context->offload_eq,
+ OFFLOAD_SEND_EQ_ENABLE_FLAG |
+ OFFLOAD_SEND_EQ_BANDS_LEVEL);
return 0;
}
@@ -167,9 +171,13 @@
equalizer_band_presets_freq,
context->band_levels);
if(context->ctl)
- offload_eq_send_params(context->ctl, context->offload_eq,
+ offload_eq_send_params(context->ctl, &context->offload_eq,
OFFLOAD_SEND_EQ_ENABLE_FLAG |
OFFLOAD_SEND_EQ_PRESET);
+ if(context->hw_acc_fd > 0)
+ hw_acc_eq_send_params(context->hw_acc_fd, &context->offload_eq,
+ OFFLOAD_SEND_EQ_ENABLE_FLAG |
+ OFFLOAD_SEND_EQ_PRESET);
return 0;
}
@@ -336,7 +344,7 @@
}
int equalizer_set_parameter(effect_context_t *context, effect_param_t *p,
- uint32_t size)
+ uint32_t size __unused)
{
equalizer_context_t *eq_ctxt = (equalizer_context_t *)context;
int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
@@ -437,6 +445,7 @@
set_config(context, &context->config);
+ eq_ctxt->hw_acc_fd = -1;
memset(&(eq_ctxt->offload_eq), 0, sizeof(struct eq_params));
offload_eq_set_preset(&(eq_ctxt->offload_eq), INVALID_PRESET);
@@ -452,9 +461,13 @@
if (!offload_eq_get_enable_flag(&(eq_ctxt->offload_eq))) {
offload_eq_set_enable_flag(&(eq_ctxt->offload_eq), true);
if (eq_ctxt->ctl)
- offload_eq_send_params(eq_ctxt->ctl, eq_ctxt->offload_eq,
+ offload_eq_send_params(eq_ctxt->ctl, &eq_ctxt->offload_eq,
OFFLOAD_SEND_EQ_ENABLE_FLAG |
OFFLOAD_SEND_EQ_BANDS_LEVEL);
+ if (eq_ctxt->hw_acc_fd > 0)
+ hw_acc_eq_send_params(eq_ctxt->hw_acc_fd, &eq_ctxt->offload_eq,
+ OFFLOAD_SEND_EQ_ENABLE_FLAG |
+ OFFLOAD_SEND_EQ_BANDS_LEVEL);
}
return 0;
}
@@ -467,8 +480,11 @@
if (offload_eq_get_enable_flag(&(eq_ctxt->offload_eq))) {
offload_eq_set_enable_flag(&(eq_ctxt->offload_eq), false);
if (eq_ctxt->ctl)
- offload_eq_send_params(eq_ctxt->ctl, eq_ctxt->offload_eq,
+ offload_eq_send_params(eq_ctxt->ctl, &eq_ctxt->offload_eq,
OFFLOAD_SEND_EQ_ENABLE_FLAG);
+ if (eq_ctxt->hw_acc_fd > 0)
+ hw_acc_eq_send_params(eq_ctxt->hw_acc_fd, &eq_ctxt->offload_eq,
+ OFFLOAD_SEND_EQ_ENABLE_FLAG);
}
return 0;
}
@@ -479,19 +495,44 @@
ALOGV("%s: ctxt %p, ctl %p", __func__, eq_ctxt, output->ctl);
eq_ctxt->ctl = output->ctl;
- if (offload_eq_get_enable_flag(&(eq_ctxt->offload_eq)))
+ if (offload_eq_get_enable_flag(&(eq_ctxt->offload_eq))) {
if (eq_ctxt->ctl)
- offload_eq_send_params(eq_ctxt->ctl, eq_ctxt->offload_eq,
+ offload_eq_send_params(eq_ctxt->ctl, &eq_ctxt->offload_eq,
OFFLOAD_SEND_EQ_ENABLE_FLAG |
OFFLOAD_SEND_EQ_BANDS_LEVEL);
+ if (eq_ctxt->hw_acc_fd > 0)
+ hw_acc_eq_send_params(eq_ctxt->hw_acc_fd, &eq_ctxt->offload_eq,
+ OFFLOAD_SEND_EQ_ENABLE_FLAG |
+ OFFLOAD_SEND_EQ_BANDS_LEVEL);
+ }
return 0;
}
-int equalizer_stop(effect_context_t *context, output_context_t *output)
+int equalizer_stop(effect_context_t *context, output_context_t *output __unused)
{
equalizer_context_t *eq_ctxt = (equalizer_context_t *)context;
ALOGV("%s: ctxt %p", __func__, eq_ctxt);
+ if (offload_eq_get_enable_flag(&(eq_ctxt->offload_eq)) &&
+ eq_ctxt->ctl) {
+ struct eq_params eq;
+ eq.enable_flag = false;
+ offload_eq_send_params(eq_ctxt->ctl, &eq, OFFLOAD_SEND_EQ_ENABLE_FLAG);
+ }
eq_ctxt->ctl = NULL;
return 0;
}
+
+int equalizer_set_mode(effect_context_t *context, int32_t hw_acc_fd)
+{
+ equalizer_context_t *eq_ctxt = (equalizer_context_t *)context;
+
+ ALOGV("%s: ctxt %p", __func__, eq_ctxt);
+ eq_ctxt->hw_acc_fd = hw_acc_fd;
+ if ((eq_ctxt->hw_acc_fd > 0) &&
+ (offload_eq_get_enable_flag(&(eq_ctxt->offload_eq))))
+ hw_acc_eq_send_params(eq_ctxt->hw_acc_fd, &eq_ctxt->offload_eq,
+ OFFLOAD_SEND_EQ_ENABLE_FLAG |
+ OFFLOAD_SEND_EQ_BANDS_LEVEL);
+ return 0;
+}
diff --git a/post_proc/equalizer.h b/post_proc/equalizer.h
index 19af186..7fec058 100644
--- a/post_proc/equalizer.h
+++ b/post_proc/equalizer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -36,6 +36,7 @@
// Offload vars
struct mixer_ctl *ctl;
+ int hw_acc_fd;
uint32_t device;
struct eq_params offload_eq;
} equalizer_context_t;
@@ -48,6 +49,8 @@
int equalizer_set_device(effect_context_t *context, uint32_t device);
+int equalizer_set_mode(effect_context_t *context, int32_t hw_acc_fd);
+
int equalizer_reset(effect_context_t *context);
int equalizer_init(effect_context_t *context);
diff --git a/post_proc/hw_accelerator.c b/post_proc/hw_accelerator.c
new file mode 100644
index 0000000..fd95db0
--- /dev/null
+++ b/post_proc/hw_accelerator.c
@@ -0,0 +1,328 @@
+/*
+ * Copyright (c) 2014, 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 "hw_accelerator_effect"
+/*#define LOG_NDEBUG 0*/
+
+#include <cutils/list.h>
+#include <cutils/log.h>
+#include <fcntl.h>
+#include <tinyalsa/asoundlib.h>
+#include <sound/audio_effects.h>
+#include <audio_effects/effect_hwaccelerator.h>
+
+#include "effect_api.h"
+#include "hw_accelerator.h"
+
+
+/* hw_accelerator UUID: 7d1580bd-297f-4683-9239-e475b6d1d69f */
+const effect_descriptor_t hw_accelerator_descriptor = {
+ EFFECT_UIID_HWACCELERATOR__,
+ {0x7d1580bd, 0x297f, 0x4683, 0x9239, {0xe4, 0x75, 0xb6, 0xd1, 0xd6, 0x9f}}, // uuid
+ EFFECT_CONTROL_API_VERSION,
+ (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_DEVICE_IND),
+ 0, /* TODO */
+ 1,
+ "HwAccelerated Library",
+ "QTI",
+};
+
+int hw_accelerator_get_parameter(effect_context_t *context,
+ effect_param_t *p, uint32_t *size)
+{
+ hw_accelerator_context_t *hw_acc_ctxt = (hw_accelerator_context_t *)context;
+ int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
+ int32_t *param_tmp = (int32_t *)p->data;
+ int32_t param = *param_tmp++;
+ void *value = p->data + voffset;
+ int i;
+
+ ALOGV("%s: ctxt %p, param %d", __func__, hw_acc_ctxt, param);
+
+ p->status = 0;
+
+ switch (param) {
+ case HW_ACCELERATOR_FD:
+ if (p->vsize < sizeof(int32_t))
+ p->status = -EINVAL;
+ p->vsize = sizeof(int32_t);
+ break;
+ default:
+ p->status = -EINVAL;
+ }
+
+ *size = sizeof(effect_param_t) + voffset + p->vsize;
+
+ if (p->status != 0)
+ return 0;
+
+ switch (param) {
+ case HW_ACCELERATOR_FD:
+ ALOGV("%s: HW_ACCELERATOR_FD", __func__);
+ *(int32_t *)value = hw_acc_ctxt->fd;
+ break;
+
+ default:
+ p->status = -EINVAL;
+ break;
+ }
+
+ return 0;
+}
+
+int hw_accelerator_set_parameter(effect_context_t *context, effect_param_t *p,
+ uint32_t size)
+{
+ hw_accelerator_context_t *hw_acc_ctxt = (hw_accelerator_context_t *)context;
+ int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
+ void *value = p->data + voffset;
+ int32_t *param_tmp = (int32_t *)p->data;
+ int32_t param = *param_tmp++;
+
+ ALOGV("%s: ctxt %p, param %d", __func__, hw_acc_ctxt, param);
+
+ p->status = 0;
+
+ switch (param) {
+ case HW_ACCELERATOR_HPX_STATE: {
+ int hpxState = (uint32_t)(*(int32_t *)value);
+ if (hpxState)
+ hw_acc_hpx_send_params(hw_acc_ctxt->fd, OFFLOAD_SEND_HPX_STATE_ON);
+ else
+ hw_acc_hpx_send_params(hw_acc_ctxt->fd, OFFLOAD_SEND_HPX_STATE_OFF);
+ break;
+ }
+ default:
+ p->status = -EINVAL;
+ break;
+ }
+
+ return 0;
+}
+
+int hw_accelerator_set_device(effect_context_t *context, uint32_t device)
+{
+ hw_accelerator_context_t *hw_acc_ctxt = (hw_accelerator_context_t *)context;
+
+ ALOGV("%s: ctxt %p", __func__, hw_acc_ctxt);
+ hw_acc_ctxt->device = device;
+ return 0;
+}
+
+int hw_accelerator_init(effect_context_t *context)
+{
+ hw_accelerator_context_t *hw_acc_ctxt = (hw_accelerator_context_t *)context;
+
+ ALOGV("%s: ctxt %p", __func__, hw_acc_ctxt);
+ context->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
+ context->config.inputCfg.channels = AUDIO_CHANNEL_OUT_7POINT1;
+ context->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ context->config.inputCfg.samplingRate = 44100;
+ context->config.inputCfg.bufferProvider.getBuffer = NULL;
+ context->config.inputCfg.bufferProvider.releaseBuffer = NULL;
+ context->config.inputCfg.bufferProvider.cookie = NULL;
+ context->config.inputCfg.mask = EFFECT_CONFIG_ALL;
+
+ context->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
+ context->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
+ context->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ context->config.outputCfg.samplingRate = 44100;
+ context->config.outputCfg.bufferProvider.getBuffer = NULL;
+ context->config.outputCfg.bufferProvider.releaseBuffer = NULL;
+ context->config.outputCfg.bufferProvider.cookie = NULL;
+ context->config.outputCfg.mask = EFFECT_CONFIG_ALL;
+
+ set_config(context, &context->config);
+
+ hw_acc_ctxt->fd = -1;
+ memset(&(hw_acc_ctxt->cfg), 0, sizeof(struct msm_hwacc_effects_config));
+
+ return 0;
+}
+
+int hw_accelerator_reset(effect_context_t *context)
+{
+ ALOGV("%s", __func__);
+ return 0;
+}
+
+int hw_accelerator_set_mode(effect_context_t *context, int32_t frame_count)
+{
+ hw_accelerator_context_t *hw_acc_ctxt = (hw_accelerator_context_t *)context;
+
+ ALOGV("%s: ctxt %p", __func__, hw_acc_ctxt);
+ hw_acc_ctxt->cfg.output.sample_rate = context->config.inputCfg.samplingRate;
+ hw_acc_ctxt->cfg.input.sample_rate = context->config.outputCfg.samplingRate;
+
+ hw_acc_ctxt->cfg.output.num_channels = popcount(context->config.inputCfg.channels);
+ hw_acc_ctxt->cfg.input.num_channels = popcount(context->config.outputCfg.channels);
+
+ hw_acc_ctxt->cfg.output.bits_per_sample = 8 *
+ audio_bytes_per_sample(context->config.inputCfg.format);
+ hw_acc_ctxt->cfg.input.bits_per_sample = 8 *
+ audio_bytes_per_sample(context->config.outputCfg.format);
+
+ ALOGV("write: sample_rate: %d, channel: %d, bit_width: %d",
+ hw_acc_ctxt->cfg.output.sample_rate, hw_acc_ctxt->cfg.output.num_channels,
+ hw_acc_ctxt->cfg.output.bits_per_sample);
+ ALOGV("read: sample_rate: %d, channel: %d, bit_width: %d",
+ hw_acc_ctxt->cfg.input.sample_rate, hw_acc_ctxt->cfg.input.num_channels,
+ hw_acc_ctxt->cfg.input.bits_per_sample);
+
+ hw_acc_ctxt->cfg.output.num_buf = 4;
+ hw_acc_ctxt->cfg.input.num_buf = 2;
+
+ hw_acc_ctxt->cfg.output.buf_size = frame_count *
+ hw_acc_ctxt->cfg.output.num_channels *
+ audio_bytes_per_sample(context->config.inputCfg.format) *
+ ((hw_acc_ctxt->cfg.output.sample_rate/hw_acc_ctxt->cfg.input.sample_rate) +
+ (hw_acc_ctxt->cfg.output.sample_rate%hw_acc_ctxt->cfg.input.sample_rate ? 1 : 0));
+ hw_acc_ctxt->cfg.input.buf_size = frame_count *
+ hw_acc_ctxt->cfg.input.num_channels *
+ audio_bytes_per_sample(context->config.outputCfg.format);
+
+ hw_acc_ctxt->cfg.meta_mode_enabled = 0;
+ /* TODO: overwrite this for effects using custom topology*/
+ hw_acc_ctxt->cfg.overwrite_topology = 0;
+ hw_acc_ctxt->cfg.topology = 0;
+
+ return 0;
+}
+
+int hw_accelerator_enable(effect_context_t *context)
+{
+ hw_accelerator_context_t *hw_acc_ctxt = (hw_accelerator_context_t *)context;
+
+ ALOGV("%s: ctxt %p", __func__, hw_acc_ctxt);
+ hw_acc_ctxt->fd = open("/dev/msm_hweffects", O_RDWR | O_NONBLOCK);
+ /* open driver */
+ if (hw_acc_ctxt->fd < 0) {
+ ALOGE("Audio Effects driver open failed");
+ return -EFAULT;
+ }
+ /* set config */
+ if (ioctl(hw_acc_ctxt->fd, AUDIO_SET_EFFECTS_CONFIG, &hw_acc_ctxt->cfg) < 0) {
+ ALOGE("setting audio effects drivers config failed");
+ if (close(hw_acc_ctxt->fd) < 0)
+ ALOGE("releasing hardware accelerated effects driver failed");
+ hw_acc_ctxt->fd = -1;
+ return -EFAULT;
+ }
+ /* start */
+ if (ioctl(hw_acc_ctxt->fd, AUDIO_START, 0) < 0) {
+ ALOGE("audio effects drivers prepare failed");
+ if (close(hw_acc_ctxt->fd) < 0)
+ ALOGE("releasing hardware accelerated effects driver failed");
+ hw_acc_ctxt->fd = -1;
+ return -EFAULT;
+ }
+ return 0;
+}
+
+int hw_accelerator_disable(effect_context_t *context)
+{
+ hw_accelerator_context_t *hw_acc_ctxt = (hw_accelerator_context_t *)context;
+
+ ALOGV("%s: ctxt %p", __func__, hw_acc_ctxt);
+ if (hw_acc_ctxt->fd > 0)
+ if (close(hw_acc_ctxt->fd) < 0)
+ ALOGE("releasing hardware accelerated effects driver failed");
+ hw_acc_ctxt->fd = -1;
+ return 0;
+}
+
+int hw_accelerator_release(effect_context_t *context)
+{
+ hw_accelerator_context_t *hw_acc_ctxt = (hw_accelerator_context_t *)context;
+
+ ALOGV("%s: ctxt %p", __func__, hw_acc_ctxt);
+ if (hw_acc_ctxt->fd > 0)
+ if (close(hw_acc_ctxt->fd) < 0)
+ ALOGE("releasing hardware accelerated effects driver failed");
+ hw_acc_ctxt->fd = -1;
+ return 0;
+}
+
+int hw_accelerator_process(effect_context_t *context, audio_buffer_t *in_buf,
+ audio_buffer_t *out_buf)
+{
+ hw_accelerator_context_t *hw_acc_ctxt = (hw_accelerator_context_t *)context;
+ struct msm_hwacc_buf_cfg buf_cfg;
+ struct msm_hwacc_buf_avail buf_avail;
+ int ret = 0;
+
+ ALOGV("%s: ctxt %p", __func__, hw_acc_ctxt);
+ if (in_buf == NULL || in_buf->raw == NULL ||
+ out_buf == NULL || out_buf->raw == NULL)
+ return -EINVAL;
+
+ buf_cfg.output_len = in_buf->frameCount *
+ audio_bytes_per_sample(context->config.inputCfg.format) *
+ hw_acc_ctxt->cfg.output.num_channels;
+ buf_cfg.input_len = out_buf->frameCount *
+ audio_bytes_per_sample(context->config.outputCfg.format) *
+ hw_acc_ctxt->cfg.input.num_channels;
+
+ if (ioctl(hw_acc_ctxt->fd, AUDIO_EFFECTS_GET_BUF_AVAIL, &buf_avail) < 0) {
+ ALOGE("AUDIO_EFFECTS_GET_BUF_AVAIL failed");
+ return -ENOMEM;
+ }
+
+ if (!hw_acc_ctxt->intial_buffer_done) {
+ if (ioctl(hw_acc_ctxt->fd, AUDIO_EFFECTS_SET_BUF_LEN, &buf_cfg) < 0) {
+ ALOGE("AUDIO_EFFECTS_BUF_CFG failed");
+ return -EFAULT;
+ }
+ if (ioctl(hw_acc_ctxt->fd, AUDIO_EFFECTS_WRITE, (char *)in_buf->raw) < 0) {
+ ALOGE("AUDIO_EFFECTS_WRITE failed");
+ return -EFAULT;
+ }
+ ALOGV("Request for more data");
+ hw_acc_ctxt->intial_buffer_done = true;
+ return -ENODATA;
+ }
+ if (buf_avail.output_num_avail > 1) {
+ if (ioctl(hw_acc_ctxt->fd, AUDIO_EFFECTS_SET_BUF_LEN, &buf_cfg) < 0) {
+ ALOGE("AUDIO_EFFECTS_BUF_CFG failed");
+ return -EFAULT;
+ }
+ if (ioctl(hw_acc_ctxt->fd, AUDIO_EFFECTS_WRITE, (char *)in_buf->raw) < 0) {
+ ALOGE("AUDIO_EFFECTS_WRITE failed");
+ return -EFAULT;
+ }
+ ret = in_buf->frameCount;
+ }
+ if (ioctl(hw_acc_ctxt->fd, AUDIO_EFFECTS_READ, (char *)out_buf->raw) < 0) {
+ ALOGE("AUDIO_EFFECTS_READ failed");
+ return -EFAULT;
+ }
+
+ return ret;
+}
diff --git a/post_proc/hw_accelerator.h b/post_proc/hw_accelerator.h
new file mode 100644
index 0000000..6387da8
--- /dev/null
+++ b/post_proc/hw_accelerator.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2014, 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 HW_ACCELERATOR_EFFECT_H_
+#define HW_ACCELERATOR_EFFECT_H_
+
+#include "bundle.h"
+
+#include <linux/msm_audio.h>
+
+#define HWACCELERATOR_OUTPUT_CHANNELS AUDIO_CHANNEL_OUT_STEREO
+
+extern const effect_descriptor_t hw_accelerator_descriptor;
+
+typedef struct hw_accelerator_context_s {
+ effect_context_t common;
+
+ int fd;
+ uint32_t device;
+ bool intial_buffer_done;
+ struct msm_hwacc_effects_config cfg;
+} hw_accelerator_context_t;
+
+int hw_accelerator_get_parameter(effect_context_t *context,
+ effect_param_t *p, uint32_t *size);
+
+int hw_accelerator_set_parameter(effect_context_t *context,
+ effect_param_t *p, uint32_t size);
+
+int hw_accelerator_set_device(effect_context_t *context, uint32_t device);
+
+int hw_accelerator_reset(effect_context_t *context);
+
+int hw_accelerator_init(effect_context_t *context);
+
+int hw_accelerator_enable(effect_context_t *context);
+
+int hw_accelerator_disable(effect_context_t *context);
+
+int hw_accelerator_release(effect_context_t *context);
+
+int hw_accelerator_set_mode(effect_context_t *context, int32_t frame_count);
+
+int hw_accelerator_process(effect_context_t *context, audio_buffer_t *in,
+ audio_buffer_t *out);
+
+#endif /* HW_ACCELERATOR_EFFECT_H_ */
diff --git a/post_proc/reverb.c b/post_proc/reverb.c
index 77ae303..b256e53 100644
--- a/post_proc/reverb.c
+++ b/post_proc/reverb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013 - 2014, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -18,7 +18,7 @@
*/
#define LOG_TAG "offload_effect_reverb"
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
#include <cutils/list.h>
#include <cutils/log.h>
@@ -102,6 +102,14 @@
context->preset = false;
}
+void reverb_insert_init(reverb_context_t *context)
+{
+ context->auxiliary = false;
+ context->preset = true;
+ context->cur_preset = REVERB_PRESET_LAST + 1;
+ context->next_preset = REVERB_DEFAULT_PRESET;
+}
+
void reverb_preset_init(reverb_context_t *context)
{
context->auxiliary = false;
@@ -125,9 +133,13 @@
context->reverb_settings.roomLevel = room_level;
offload_reverb_set_room_level(&(context->offload_reverb), room_level);
if (context->ctl)
- offload_reverb_send_params(context->ctl, context->offload_reverb,
+ offload_reverb_send_params(context->ctl, &context->offload_reverb,
OFFLOAD_SEND_REVERB_ENABLE_FLAG |
OFFLOAD_SEND_REVERB_ROOM_LEVEL);
+ if (context->hw_acc_fd > 0)
+ hw_acc_reverb_send_params(context->hw_acc_fd, &context->offload_reverb,
+ OFFLOAD_SEND_REVERB_ENABLE_FLAG |
+ OFFLOAD_SEND_REVERB_ROOM_LEVEL);
}
int16_t reverb_get_room_hf_level(reverb_context_t *context)
@@ -143,9 +155,13 @@
context->reverb_settings.roomHFLevel = room_hf_level;
offload_reverb_set_room_hf_level(&(context->offload_reverb), room_hf_level);
if (context->ctl)
- offload_reverb_send_params(context->ctl, context->offload_reverb,
+ offload_reverb_send_params(context->ctl, &context->offload_reverb,
OFFLOAD_SEND_REVERB_ENABLE_FLAG |
OFFLOAD_SEND_REVERB_ROOM_HF_LEVEL);
+ if (context->hw_acc_fd > 0)
+ hw_acc_reverb_send_params(context->hw_acc_fd, &context->offload_reverb,
+ OFFLOAD_SEND_REVERB_ENABLE_FLAG |
+ OFFLOAD_SEND_REVERB_ROOM_HF_LEVEL);
}
uint32_t reverb_get_decay_time(reverb_context_t *context)
@@ -161,9 +177,13 @@
context->reverb_settings.decayTime = decay_time;
offload_reverb_set_decay_time(&(context->offload_reverb), decay_time);
if (context->ctl)
- offload_reverb_send_params(context->ctl, context->offload_reverb,
+ offload_reverb_send_params(context->ctl, &context->offload_reverb,
OFFLOAD_SEND_REVERB_ENABLE_FLAG |
OFFLOAD_SEND_REVERB_DECAY_TIME);
+ if (context->hw_acc_fd > 0)
+ hw_acc_reverb_send_params(context->hw_acc_fd, &context->offload_reverb,
+ OFFLOAD_SEND_REVERB_ENABLE_FLAG |
+ OFFLOAD_SEND_REVERB_DECAY_TIME);
}
int16_t reverb_get_decay_hf_ratio(reverb_context_t *context)
@@ -179,9 +199,13 @@
context->reverb_settings.decayHFRatio = decay_hf_ratio;
offload_reverb_set_decay_hf_ratio(&(context->offload_reverb), decay_hf_ratio);
if (context->ctl)
- offload_reverb_send_params(context->ctl, context->offload_reverb,
+ offload_reverb_send_params(context->ctl, &context->offload_reverb,
OFFLOAD_SEND_REVERB_ENABLE_FLAG |
OFFLOAD_SEND_REVERB_DECAY_HF_RATIO);
+ if (context->hw_acc_fd > 0)
+ hw_acc_reverb_send_params(context->hw_acc_fd, &context->offload_reverb,
+ OFFLOAD_SEND_REVERB_ENABLE_FLAG |
+ OFFLOAD_SEND_REVERB_DECAY_HF_RATIO);
}
int16_t reverb_get_reverb_level(reverb_context_t *context)
@@ -197,9 +221,13 @@
context->reverb_settings.reverbLevel = reverb_level;
offload_reverb_set_reverb_level(&(context->offload_reverb), reverb_level);
if (context->ctl)
- offload_reverb_send_params(context->ctl, context->offload_reverb,
+ offload_reverb_send_params(context->ctl, &context->offload_reverb,
OFFLOAD_SEND_REVERB_ENABLE_FLAG |
OFFLOAD_SEND_REVERB_LEVEL);
+ if (context->hw_acc_fd > 0)
+ hw_acc_reverb_send_params(context->hw_acc_fd, &context->offload_reverb,
+ OFFLOAD_SEND_REVERB_ENABLE_FLAG |
+ OFFLOAD_SEND_REVERB_LEVEL);
}
int16_t reverb_get_diffusion(reverb_context_t *context)
@@ -215,9 +243,13 @@
context->reverb_settings.diffusion = diffusion;
offload_reverb_set_diffusion(&(context->offload_reverb), diffusion);
if (context->ctl)
- offload_reverb_send_params(context->ctl, context->offload_reverb,
+ offload_reverb_send_params(context->ctl, &context->offload_reverb,
OFFLOAD_SEND_REVERB_ENABLE_FLAG |
OFFLOAD_SEND_REVERB_DIFFUSION);
+ if (context->hw_acc_fd > 0)
+ hw_acc_reverb_send_params(context->hw_acc_fd, &context->offload_reverb,
+ OFFLOAD_SEND_REVERB_ENABLE_FLAG |
+ OFFLOAD_SEND_REVERB_DIFFUSION);
}
int16_t reverb_get_density(reverb_context_t *context)
@@ -233,9 +265,13 @@
context->reverb_settings.density = density;
offload_reverb_set_density(&(context->offload_reverb), density);
if (context->ctl)
- offload_reverb_send_params(context->ctl, context->offload_reverb,
+ offload_reverb_send_params(context->ctl, &context->offload_reverb,
OFFLOAD_SEND_REVERB_ENABLE_FLAG |
OFFLOAD_SEND_REVERB_DENSITY);
+ if (context->hw_acc_fd > 0)
+ hw_acc_reverb_send_params(context->hw_acc_fd, &context->offload_reverb,
+ OFFLOAD_SEND_REVERB_ENABLE_FLAG |
+ OFFLOAD_SEND_REVERB_DENSITY);
}
void reverb_set_preset(reverb_context_t *context, int16_t preset)
@@ -249,9 +285,13 @@
offload_reverb_set_enable_flag(&(context->offload_reverb), enable);
if (context->ctl)
- offload_reverb_send_params(context->ctl, context->offload_reverb,
+ offload_reverb_send_params(context->ctl, &context->offload_reverb,
OFFLOAD_SEND_REVERB_ENABLE_FLAG |
OFFLOAD_SEND_REVERB_PRESET);
+ if (context->hw_acc_fd > 0)
+ hw_acc_reverb_send_params(context->hw_acc_fd, &context->offload_reverb,
+ OFFLOAD_SEND_REVERB_ENABLE_FLAG |
+ OFFLOAD_SEND_REVERB_PRESET);
}
void reverb_set_all_properties(reverb_context_t *context,
@@ -266,7 +306,7 @@
context->reverb_settings.diffusion = reverb_settings->diffusion;
context->reverb_settings.density = reverb_settings->density;
if (context->ctl)
- offload_reverb_send_params(context->ctl, context->offload_reverb,
+ offload_reverb_send_params(context->ctl, &context->offload_reverb,
OFFLOAD_SEND_REVERB_ENABLE_FLAG |
OFFLOAD_SEND_REVERB_ROOM_LEVEL |
OFFLOAD_SEND_REVERB_ROOM_HF_LEVEL |
@@ -275,6 +315,16 @@
OFFLOAD_SEND_REVERB_LEVEL |
OFFLOAD_SEND_REVERB_DIFFUSION |
OFFLOAD_SEND_REVERB_DENSITY);
+ if (context->hw_acc_fd > 0)
+ hw_acc_reverb_send_params(context->hw_acc_fd, &context->offload_reverb,
+ OFFLOAD_SEND_REVERB_ENABLE_FLAG |
+ OFFLOAD_SEND_REVERB_ROOM_LEVEL |
+ OFFLOAD_SEND_REVERB_ROOM_HF_LEVEL |
+ OFFLOAD_SEND_REVERB_DECAY_TIME |
+ OFFLOAD_SEND_REVERB_DECAY_HF_RATIO |
+ OFFLOAD_SEND_REVERB_LEVEL |
+ OFFLOAD_SEND_REVERB_DIFFUSION |
+ OFFLOAD_SEND_REVERB_DENSITY);
}
void reverb_load_preset(reverb_context_t *context)
@@ -433,7 +483,7 @@
}
int reverb_set_parameter(effect_context_t *context, effect_param_t *p,
- uint32_t size)
+ uint32_t size __unused)
{
reverb_context_t *reverb_ctxt = (reverb_context_t *)context;
int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
@@ -549,6 +599,7 @@
set_config(context, &context->config);
+ reverb_ctxt->hw_acc_fd = -1;
memset(&(reverb_ctxt->reverb_settings), 0, sizeof(reverb_settings_t));
memset(&(reverb_ctxt->offload_reverb), 0, sizeof(struct reverb_params));
@@ -579,8 +630,12 @@
offload_reverb_set_enable_flag(&(reverb_ctxt->offload_reverb), false);
if (reverb_ctxt->ctl)
offload_reverb_send_params(reverb_ctxt->ctl,
- reverb_ctxt->offload_reverb,
+ &reverb_ctxt->offload_reverb,
OFFLOAD_SEND_REVERB_ENABLE_FLAG);
+ if (reverb_ctxt->hw_acc_fd > 0)
+ hw_acc_reverb_send_params(reverb_ctxt->hw_acc_fd,
+ &reverb_ctxt->offload_reverb,
+ OFFLOAD_SEND_REVERB_ENABLE_FLAG);
}
return 0;
}
@@ -593,21 +648,48 @@
reverb_ctxt->ctl = output->ctl;
if (offload_reverb_get_enable_flag(&(reverb_ctxt->offload_reverb))) {
if (reverb_ctxt->ctl && reverb_ctxt->preset) {
- offload_reverb_send_params(reverb_ctxt->ctl, reverb_ctxt->offload_reverb,
+ offload_reverb_send_params(reverb_ctxt->ctl, &reverb_ctxt->offload_reverb,
OFFLOAD_SEND_REVERB_ENABLE_FLAG |
OFFLOAD_SEND_REVERB_PRESET);
}
+ if ((reverb_ctxt->hw_acc_fd > 0) && reverb_ctxt->preset) {
+ hw_acc_reverb_send_params(reverb_ctxt->hw_acc_fd,
+ &reverb_ctxt->offload_reverb,
+ OFFLOAD_SEND_REVERB_ENABLE_FLAG |
+ OFFLOAD_SEND_REVERB_PRESET);
+ }
}
return 0;
}
-int reverb_stop(effect_context_t *context, output_context_t *output)
+int reverb_stop(effect_context_t *context, output_context_t *output __unused)
{
reverb_context_t *reverb_ctxt = (reverb_context_t *)context;
ALOGV("%s: ctxt %p", __func__, reverb_ctxt);
+ if (offload_reverb_get_enable_flag(&(reverb_ctxt->offload_reverb)) &&
+ reverb_ctxt->ctl) {
+ struct reverb_params reverb;
+ reverb.enable_flag = false;
+ offload_reverb_send_params(reverb_ctxt->ctl, &reverb,
+ OFFLOAD_SEND_REVERB_ENABLE_FLAG);
+ }
reverb_ctxt->ctl = NULL;
return 0;
}
+int reverb_set_mode(effect_context_t *context, int32_t hw_acc_fd)
+{
+ reverb_context_t *reverb_ctxt = (reverb_context_t *)context;
+
+ ALOGV("%s: ctxt %p", __func__, reverb_ctxt);
+ reverb_ctxt->hw_acc_fd = hw_acc_fd;
+ if ((reverb_ctxt->hw_acc_fd > 0) &&
+ (offload_reverb_get_enable_flag(&(reverb_ctxt->offload_reverb))))
+ hw_acc_reverb_send_params(reverb_ctxt->hw_acc_fd,
+ &reverb_ctxt->offload_reverb,
+ OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG |
+ OFFLOAD_SEND_BASSBOOST_STRENGTH);
+ return 0;
+}
diff --git a/post_proc/reverb.h b/post_proc/reverb.h
index 63192eb..991151e 100644
--- a/post_proc/reverb.h
+++ b/post_proc/reverb.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -47,6 +47,7 @@
// Offload vars
struct mixer_ctl *ctl;
+ int hw_acc_fd;
bool auxiliary;
bool preset;
uint16_t cur_preset;
@@ -61,6 +62,8 @@
void reverb_preset_init(reverb_context_t *context);
+void reverb_insert_init(reverb_context_t *context);
+
int reverb_get_parameter(effect_context_t *context, effect_param_t *p,
uint32_t *size);
@@ -69,6 +72,8 @@
int reverb_set_device(effect_context_t *context, uint32_t device);
+int reverb_set_mode(effect_context_t *context, int32_t hw_acc_fd);
+
int reverb_reset(effect_context_t *context);
int reverb_init(effect_context_t *context);
diff --git a/post_proc/virtualizer.c b/post_proc/virtualizer.c
index 9ed1ac5..f6e2881 100644
--- a/post_proc/virtualizer.c
+++ b/post_proc/virtualizer.c
@@ -18,7 +18,7 @@
*/
#define LOG_TAG "offload_effect_virtualizer"
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
#include <cutils/list.h>
#include <cutils/log.h>
@@ -58,9 +58,14 @@
offload_virtualizer_set_strength(&(context->offload_virt), strength);
if (context->ctl)
- offload_virtualizer_send_params(context->ctl, context->offload_virt,
+ offload_virtualizer_send_params(context->ctl, &context->offload_virt,
OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG |
OFFLOAD_SEND_VIRTUALIZER_STRENGTH);
+ if (context->hw_acc_fd > 0)
+ hw_acc_virtualizer_send_params(context->hw_acc_fd,
+ &context->offload_virt,
+ OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG |
+ OFFLOAD_SEND_VIRTUALIZER_STRENGTH);
return 0;
}
@@ -162,8 +167,12 @@
offload_virtualizer_set_enable_flag(&(virt_ctxt->offload_virt), false);
if (virt_ctxt->ctl)
offload_virtualizer_send_params(virt_ctxt->ctl,
- virt_ctxt->offload_virt,
+ &virt_ctxt->offload_virt,
OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG);
+ if (virt_ctxt->hw_acc_fd > 0)
+ hw_acc_virtualizer_send_params(virt_ctxt->hw_acc_fd,
+ &virt_ctxt->offload_virt,
+ OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG);
}
virt_ctxt->temp_disabled = true;
ALOGI("%s: ctxt %p, disabled based on device", __func__, virt_ctxt);
@@ -174,8 +183,12 @@
offload_virtualizer_set_enable_flag(&(virt_ctxt->offload_virt), true);
if (virt_ctxt->ctl)
offload_virtualizer_send_params(virt_ctxt->ctl,
- virt_ctxt->offload_virt,
+ &virt_ctxt->offload_virt,
OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG);
+ if (virt_ctxt->hw_acc_fd > 0)
+ hw_acc_virtualizer_send_params(virt_ctxt->hw_acc_fd,
+ &virt_ctxt->offload_virt,
+ OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG);
}
virt_ctxt->temp_disabled = false;
}
@@ -216,6 +229,7 @@
set_config(context, &context->config);
virt_ctxt->temp_disabled = false;
+ virt_ctxt->hw_acc_fd = -1;
memset(&(virt_ctxt->offload_virt), 0, sizeof(struct virtualizer_params));
return 0;
@@ -232,9 +246,14 @@
offload_virtualizer_set_enable_flag(&(virt_ctxt->offload_virt), true);
if (virt_ctxt->ctl && virt_ctxt->strength)
offload_virtualizer_send_params(virt_ctxt->ctl,
- virt_ctxt->offload_virt,
+ &virt_ctxt->offload_virt,
OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG |
- OFFLOAD_SEND_BASSBOOST_STRENGTH);
+ OFFLOAD_SEND_VIRTUALIZER_STRENGTH);
+ if ((virt_ctxt->hw_acc_fd > 0) && virt_ctxt->strength)
+ hw_acc_virtualizer_send_params(virt_ctxt->hw_acc_fd,
+ &virt_ctxt->offload_virt,
+ OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG |
+ OFFLOAD_SEND_VIRTUALIZER_STRENGTH);
}
return 0;
}
@@ -248,8 +267,12 @@
offload_virtualizer_set_enable_flag(&(virt_ctxt->offload_virt), false);
if (virt_ctxt->ctl)
offload_virtualizer_send_params(virt_ctxt->ctl,
- virt_ctxt->offload_virt,
+ &virt_ctxt->offload_virt,
OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG);
+ if (virt_ctxt->hw_acc_fd > 0)
+ hw_acc_virtualizer_send_params(virt_ctxt->hw_acc_fd,
+ &virt_ctxt->offload_virt,
+ OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG);
}
return 0;
}
@@ -260,19 +283,47 @@
ALOGV("%s: ctxt %p, ctl %p", __func__, virt_ctxt, output->ctl);
virt_ctxt->ctl = output->ctl;
- if (offload_virtualizer_get_enable_flag(&(virt_ctxt->offload_virt)))
+ if (offload_virtualizer_get_enable_flag(&(virt_ctxt->offload_virt))) {
if (virt_ctxt->ctl)
- offload_virtualizer_send_params(virt_ctxt->ctl, virt_ctxt->offload_virt,
+ offload_virtualizer_send_params(virt_ctxt->ctl, &virt_ctxt->offload_virt,
OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG |
OFFLOAD_SEND_VIRTUALIZER_STRENGTH);
+ if (virt_ctxt->hw_acc_fd > 0)
+ hw_acc_virtualizer_send_params(virt_ctxt->hw_acc_fd,
+ &virt_ctxt->offload_virt,
+ OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG |
+ OFFLOAD_SEND_VIRTUALIZER_STRENGTH);
+ }
return 0;
}
-int virtualizer_stop(effect_context_t *context, output_context_t *output)
+int virtualizer_stop(effect_context_t *context, output_context_t *output __unused)
{
virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)context;
ALOGV("%s: ctxt %p", __func__, virt_ctxt);
+ if (offload_virtualizer_get_enable_flag(&(virt_ctxt->offload_virt)) &&
+ virt_ctxt->ctl) {
+ struct virtualizer_params virt;
+ virt.enable_flag = false;
+ offload_virtualizer_send_params(virt_ctxt->ctl, &virt,
+ OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG);
+ }
virt_ctxt->ctl = NULL;
return 0;
}
+
+int virtualizer_set_mode(effect_context_t *context, int32_t hw_acc_fd)
+{
+ virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)context;
+
+ ALOGV("%s: ctxt %p", __func__, virt_ctxt);
+ virt_ctxt->hw_acc_fd = hw_acc_fd;
+ if ((virt_ctxt->hw_acc_fd > 0) &&
+ (offload_virtualizer_get_enable_flag(&(virt_ctxt->offload_virt))))
+ hw_acc_virtualizer_send_params(virt_ctxt->hw_acc_fd,
+ &virt_ctxt->offload_virt,
+ OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG |
+ OFFLOAD_SEND_VIRTUALIZER_STRENGTH);
+ return 0;
+}
diff --git a/post_proc/virtualizer.h b/post_proc/virtualizer.h
index 4a5005f..440c8a2 100644
--- a/post_proc/virtualizer.h
+++ b/post_proc/virtualizer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -31,6 +31,7 @@
// Offload vars
struct mixer_ctl *ctl;
+ int hw_acc_fd;
bool temp_disabled;
uint32_t device;
struct virtualizer_params offload_virt;
@@ -44,6 +45,8 @@
int virtualizer_set_device(effect_context_t *context, uint32_t device);
+int virtualizer_set_mode(effect_context_t *context, int32_t hw_acc_fd);
+
int virtualizer_reset(effect_context_t *context);
int virtualizer_init(effect_context_t *context);