Merge "hal: bug fixes for PCM offload"
diff --git a/hal/Android.mk b/hal/Android.mk
index 1e0e52b..0ed8b44 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -125,6 +125,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
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 8c52eaa..e6964fc 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"
@@ -40,6 +58,7 @@
bool aanc_enabled;
bool custom_stereo_enabled;
uint32_t proxy_channel_num;
+ bool hpx_enabled;
};
static struct audio_extn_module aextnmod = {
@@ -47,6 +66,7 @@
.aanc_enabled = 0,
.custom_stereo_enabled = 0,
.proxy_channel_num = 2,
+ .hpx_enabled = 0,
};
#define AUDIO_PARAMETER_KEY_ANC "anc_enabled"
@@ -55,6 +75,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)
@@ -108,6 +129,57 @@
}
#endif /* CUSTOM_STEREO_ENABLED */
+#ifndef DTS_EAGLE
+#define audio_extn_hpx_set_parameters(adev, parms) (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);
+ }
+}
+
+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
@@ -437,9 +509,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,
@@ -450,6 +524,7 @@
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);
kv_pairs = str_parms_to_str(reply);
ALOGD_IF(kv_pairs != NULL, "%s: returns %s", __func__, kv_pairs);
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 84192c7..556ebcf 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,6 +269,28 @@
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);
#else
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_hw.c b/hal/audio_hw.c
index 2299b02..26088eb 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"
@@ -1196,6 +1214,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);
@@ -1212,6 +1232,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);
@@ -1362,6 +1383,9 @@
!(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);
}
@@ -1514,6 +1538,11 @@
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);
@@ -1523,6 +1552,7 @@
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__);
@@ -1860,6 +1890,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);
}
@@ -2070,6 +2106,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;
@@ -2238,6 +2278,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);
}
@@ -2261,6 +2306,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);
}
@@ -2530,7 +2579,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:
@@ -2802,13 +2852,14 @@
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) {
@@ -2916,6 +2967,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;
@@ -2946,6 +3002,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)
@@ -3558,6 +3615,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 818389a..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
@@ -300,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/msm8974/platform.c b/hal/msm8974/platform.c
index 7f54a78..1c19a61 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -3164,10 +3164,12 @@
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;
@@ -3222,6 +3224,7 @@
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;
diff --git a/post_proc/Android.mk b/post_proc/Android.mk
index 6ed1416..720d3dd 100644
--- a/post_proc/Android.mk
+++ b/post_proc/Android.mk
@@ -13,10 +13,15 @@
bass_boost.c \
virtualizer.c \
reverb.c \
- effect_api.c
+ effect_api.c \
+ effect_util.c
LOCAL_CFLAGS+= -O2 -fvisibility=hidden
+ifneq ($(strip $(AUDIO_FEATURE_DISABLED_DTS_EAGLE)),true)
+ LOCAL_CFLAGS += -DDTS_EAGLE
+endif
+
LOCAL_SHARED_LIBRARIES := \
libcutils \
liblog \
diff --git a/post_proc/bundle.c b/post_proc/bundle.c
index 0db2e37..a0a6765 100644
--- a/post_proc/bundle.c
+++ b/post_proc/bundle.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 "offload_effect_bundle"
@@ -32,6 +50,10 @@
#include "virtualizer.h"
#include "reverb.h"
+#ifdef DTS_EAGLE
+#include "effect_util.h"
+#endif
+
enum {
EFFECT_STATE_UNINITIALIZED,
EFFECT_STATE_INITIALIZED,
@@ -190,6 +212,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;
@@ -285,6 +311,10 @@
list_remove(&out_ctxt->outputs_list_node);
+#ifdef DTS_EAGLE
+ remove_effect_state_node(pcm_id);
+#endif
+
free(out_ctxt);
exit:
diff --git a/post_proc/effect_api.c b/post_proc/effect_api.c
index 971b67f..327ddb9 100644
--- a/post_proc/effect_api.c
+++ b/post_proc/effect_api.c
@@ -25,6 +25,24 @@
* 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"
@@ -40,9 +58,13 @@
#include <cutils/log.h>
#include <tinyalsa/asoundlib.h>
#include <sound/audio_effects.h>
-
+#include <sound/devdep_params.h>
#include "effect_api.h"
+#ifdef DTS_EAGLE
+#include "effect_util.h"
+#endif
+
#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
#define OFFLOAD_PRESET_START_OFFSET_FOR_OPENSL 19
@@ -114,6 +136,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 +153,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,
@@ -190,6 +220,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 +237,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,
@@ -279,6 +317,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,6 +350,10 @@
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,
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_*/