summaryrefslogtreecommitdiffstats
path: root/msm8909/hal/audio_extn/a2dp.c
diff options
context:
space:
mode:
authorUday Kishore Pasupuleti <upasupul@codeaurora.org>2016-01-06 19:12:41 -0800
committerPrashant Malani <pmalani@google.com>2016-01-08 17:00:16 -0800
commit582e0a5e965897ea54ecfa5fe206797dab577a45 (patch)
tree3d99bdf637b54008f1e906975d75f7de7bfb6fb6 /msm8909/hal/audio_extn/a2dp.c
parentbefe610a877c3b150a6dd90cf358df4945b8f9a6 (diff)
downloadhardware_qcom_audio-582e0a5e965897ea54ecfa5fe206797dab577a45.tar.gz
hardware_qcom_audio-582e0a5e965897ea54ecfa5fe206797dab577a45.tar.bz2
hardware_qcom_audio-582e0a5e965897ea54ecfa5fe206797dab577a45.zip
audio: msm8909w caf release LW.BR.1.0-00410-8x09w.0
MSM8909w Audio HAL code copied from CAF release LW.BR.1.0-00410-8x09w.0 dbcce50 hal: Port wcd9326 changes to 8909 410c530 hal: update error handling for pcm_prepare failures ff79309 hal: fix compilation issues with audio FM extention 762d7eb policy_hal: add support for fm device loopback 7c418f9 audio_policy: modify few methods to appropriately override base 8b12163 audio: Add support to enable split A2DP a0559fa Revert "Revert "policy_hal: Function prototype correction for custom policy"." Fixed makefiles to be compatible with PDK without kernel source Change-Id: I9c6f2139adee62426b877516deeb41d4ed8052b2
Diffstat (limited to 'msm8909/hal/audio_extn/a2dp.c')
-rw-r--r--msm8909/hal/audio_extn/a2dp.c201
1 files changed, 201 insertions, 0 deletions
diff --git a/msm8909/hal/audio_extn/a2dp.c b/msm8909/hal/audio_extn/a2dp.c
new file mode 100644
index 00000000..6b22b692
--- /dev/null
+++ b/msm8909/hal/audio_extn/a2dp.c
@@ -0,0 +1,201 @@
+/*
+* Copyright (c) 2015, 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 "split_a2dp"
+/*#define LOG_NDEBUG 0*/
+#define LOG_NDDEBUG 0
+#include <errno.h>
+#include <cutils/log.h>
+
+#include "audio_hw.h"
+#include "platform.h"
+#include "platform_api.h"
+#include <stdlib.h>
+#include <cutils/str_parms.h>
+#include <hardware/audio.h>
+#include <hardware/hardware.h>
+
+#ifdef SPLIT_A2DP_ENABLED
+
+struct a2dp_data{
+ struct audio_stream_out *a2dp_stream;
+ struct audio_hw_device *a2dp_device;
+ bool a2dp_started;
+ bool a2dp_suspended;
+};
+
+struct a2dp_data a2dp;
+
+#define AUDIO_PARAMETER_A2DP_STARTED "A2dpStarted"
+
+static int open_a2dp_output()
+{
+ hw_module_t *mod;
+ int format = AUDIO_FORMAT_PCM_16_BIT;
+ int rc=0;
+ uint32_t channels = AUDIO_CHANNEL_OUT_STEREO;
+ uint32_t sampleRate = DEFAULT_OUTPUT_SAMPLING_RATE;
+ struct audio_config config;
+
+ ALOGV("open_a2dp_output");
+
+ config.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
+ config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ config.format = AUDIO_FORMAT_PCM_16_BIT;
+
+ if (a2dp.a2dp_device == NULL){
+ rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, (const char*)"a2dp",
+ (const hw_module_t**)&mod);
+ if (rc != 0) {
+ ALOGE("Could not get a2dp hardware module");
+ return rc;
+ }
+ ALOGV("Opening A2DP device HAL for the first time");
+ rc = audio_hw_device_open(mod, &a2dp.a2dp_device);
+ if (rc != 0) {
+ ALOGE("couldn't open a2dp audio hw device");
+ return rc;
+ }
+ }
+
+ rc = a2dp.a2dp_device->open_output_stream(a2dp.a2dp_device, 0,AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
+ (audio_output_flags_t)AUDIO_OUTPUT_FLAG_NONE, &config, &a2dp.a2dp_stream, NULL);
+
+ if( rc != 0 ) {
+ ALOGE("Failed to open output stream for a2dp: status %d", rc);
+ }
+
+ a2dp.a2dp_suspended = false;
+ return rc;
+}
+
+static int close_a2dp_output()
+{
+
+ ALOGV("close_a2dp_output");
+ if(!a2dp.a2dp_device && !a2dp.a2dp_stream){
+ ALOGE("No Active A2dp output found");
+ return 0;
+ }
+
+ a2dp.a2dp_device->close_output_stream(a2dp.a2dp_device, a2dp.a2dp_stream);
+ a2dp.a2dp_stream = NULL;
+ a2dp.a2dp_started = false;
+ a2dp.a2dp_suspended = true;
+
+ return 0;
+}
+
+void audio_extn_a2dp_set_parameters(struct str_parms *parms)
+{
+ int ret, val;
+ char value[32]={0};
+
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value,
+ sizeof(value));
+ if( ret >= 0) {
+ val = atoi(value);
+ if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
+ ALOGV("Received device connect request for A2DP");
+ open_a2dp_output();
+ }
+ }
+
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value,
+ sizeof(value));
+
+ if( ret >= 0) {
+ val = atoi(value);
+ if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
+ ALOGV("Received device dis- connect request");
+ close_a2dp_output();
+ }
+ }
+
+ ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
+ if (ret >= 0) {
+ if (a2dp.a2dp_device && a2dp.a2dp_stream) {
+ a2dp.a2dp_device->set_parameters(a2dp.a2dp_device, str_parms_to_str(parms));
+ if (!strncmp(value,"true",sizeof(value))) {
+ a2dp.a2dp_suspended = true;
+ } else {
+ a2dp.a2dp_suspended = false;
+ }
+ }
+ }
+}
+
+void audio_extn_a2dp_start_playback()
+{
+ int ret = 0;
+ char buf[20]={0};
+
+ if (!a2dp.a2dp_started && a2dp.a2dp_device && a2dp.a2dp_stream) {
+
+ snprintf(buf,sizeof(buf),"%s=true",AUDIO_PARAMETER_A2DP_STARTED);
+ /* This call indicates BT HAL to start playback */
+ ret = a2dp.a2dp_device->set_parameters(a2dp.a2dp_device, buf);
+ if (ret < 0 ) {
+ ALOGE("BT controller start failed, retry on the next write");
+ a2dp.a2dp_started = false;
+ } else {
+ a2dp.a2dp_started = true;
+ ALOGV("Start playback successful to BT HAL");
+ }
+ }
+}
+
+void audio_extn_a2dp_stop_playback()
+{
+ int ret =0;
+ char buf[20]={0};
+
+ if ( a2dp.a2dp_started && a2dp.a2dp_device && a2dp.a2dp_stream) {
+
+ snprintf(buf,sizeof(buf),"%s=false",AUDIO_PARAMETER_A2DP_STARTED);
+
+ ret = a2dp.a2dp_device->set_parameters(a2dp.a2dp_device, buf);
+
+ if (ret < 0)
+ ALOGE("out_standby to BT HAL failed");
+ else
+ ALOGV("out_standby to BT HAL successful");
+
+ }
+ a2dp.a2dp_started = false;
+ a2dp.a2dp_suspended = true;
+}
+
+void audio_extn_a2dp_init ()
+{
+ a2dp.a2dp_started = false;
+ a2dp.a2dp_suspended = true;
+ a2dp.a2dp_stream = NULL;
+ a2dp.a2dp_device = NULL;
+}
+#endif // SPLIT_A2DP_ENABLED