summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNishanth Menon2014-11-11 17:28:38 -0600
committerNishanth Menon2014-11-11 17:28:38 -0600
commit88fc70c0850794fb0bce52f63dfcc0d8f3d5062e (patch)
treebd2acd9a43827c481dfcca8049f0206c2f7979ef
downloaddevice-ti-x15-88fc70c0850794fb0bce52f63dfcc0d8f3d5062e.tar.gz
device-ti-x15-88fc70c0850794fb0bce52f63dfcc0d8f3d5062e.tar.xz
device-ti-x15-88fc70c0850794fb0bce52f63dfcc0d8f3d5062e.zip
initial baseline from TI's code
Signed-off-by: Nishanth Menon <nm@ti.com>
-rw-r--r--Android.mk55
-rw-r--r--AndroidProducts.mk17
-rw-r--r--Atmel_maXTouch_Touchscreen.idc25
-rw-r--r--BoardConfig.mk80
-rw-r--r--CleanSpec.mk51
-rw-r--r--LDC_3001_TouchScreen_Controller.idc25
-rw-r--r--audio/Android.mk37
-rw-r--r--audio/legacy/Android.mk51
-rw-r--r--audio/legacy/audio_hw.c1674
-rw-r--r--audio/legacy/audio_policy.conf94
-rw-r--r--audio/mixer_paths.xml85
-rw-r--r--audio/multizone/Android.mk53
-rw-r--r--audio/multizone/AudioHw.cpp1276
-rw-r--r--audio/multizone/AudioHw.h251
-rw-r--r--audio/multizone/audio_hw.cpp562
-rw-r--r--audio/multizone/audio_policy.conf116
-rw-r--r--bluetooth/bdroid_buildcfg.h22
-rw-r--r--bootanimation.zipbin0 -> 3713650 bytes
-rw-r--r--device.mk155
-rw-r--r--egl.cfg2
-rwxr-xr-xfastboot.sh261
-rw-r--r--fstab.jacinto6evmboard15
-rw-r--r--full_jacinto6evm.mk32
-rw-r--r--init.jacinto6evmboard.rc207
-rw-r--r--init.jacinto6evmboard.usb.rc97
-rw-r--r--kernelbin0 -> 5791320 bytes
-rw-r--r--media_codecs.xml56
-rw-r--r--media_profiles.xml664
-rw-r--r--overlay/frameworks/base/core/res/res/values/config.xml104
-rw-r--r--overlay/frameworks/base/core/res/res/xml/storage_list.xml56
-rw-r--r--overlay/frameworks/base/packages/SettingsProvider/res/values/config.xml24
-rw-r--r--overlay/packages/apps/Launcher2/res/xml/default_workspace.xml91
-rw-r--r--overlay/packages/apps/SoundRecorder/res/values/styles.xml23
-rw-r--r--sepolicy/healthd.te1
-rw-r--r--system.prop2
-rw-r--r--tablet_core_hardware_jacinto6evm.xml35
-rw-r--r--ueventd.jacinto6evmboard.rc29
-rw-r--r--vendorsetup.sh18
38 files changed, 6346 insertions, 0 deletions
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..37d2bcb
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,55 @@
1#
2# Copyright (C) 2011 The Android Open-Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16
17# WARNING: Everything listed here will be built on ALL platforms,
18# including x86, the emulator, and the SDK. Modules must be uniquely
19# named (liblights.panda), and must build everywhere, or limit themselves
20# to only building on ARM if they include assembly. Individual makefiles
21# are responsible for having their own logic, for fine-grained control.
22
23LOCAL_PATH := $(call my-dir)
24
25# protect makefile from other boards
26# if some modules are built directly from this directory (not subdirectories),
27# their rules should be written here.
28ifeq ($(TARGET_DEVICE),jacinto6evm)
29include $(CLEAR_VARS)
30
31LOCAL_MODULE := jacinto6evm_hdcp_keys
32LOCAL_MODULE_TAGS := optional
33LOCAL_MODULE_CLASS := FAKE
34LOCAL_MODULE_SUFFIX := -timestamp
35
36include $(BUILD_SYSTEM)/base_rules.mk
37
38$(LOCAL_BUILT_MODULE): HDCP_KEYS_FILE := /factory/hdcp.keys
39$(LOCAL_BUILT_MODULE): SYMLINK := $(TARGET_OUT_VENDOR)/firmware/hdcp.keys
40$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/Android.mk
41$(LOCAL_BUILT_MODULE):
42 $(hide) echo "Symlink: $(SYMLINK) -> $(HDCP_KEYS_FILE)"
43 $(hide) mkdir -p $(dir $@)
44 $(hide) mkdir -p $(dir $(SYMLINK))
45 $(hide) rm -rf $@
46 $(hide) rm -rf $(SYMLINK)
47 $(hide) ln -sf $(HDCP_KEYS_FILE) $(SYMLINK)
48 $(hide) touch $@
49
50# if some modules are built directly from this directory (not subdirectories),
51# their rules should be written here.
52
53include $(call all-makefiles-under,$(LOCAL_PATH))
54
55endif
diff --git a/AndroidProducts.mk b/AndroidProducts.mk
new file mode 100644
index 0000000..26b97c7
--- /dev/null
+++ b/AndroidProducts.mk
@@ -0,0 +1,17 @@
1#
2# Copyright (C) 2011 The Android Open-Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16
17PRODUCT_MAKEFILES := $(LOCAL_DIR)/full_jacinto6evm.mk
diff --git a/Atmel_maXTouch_Touchscreen.idc b/Atmel_maXTouch_Touchscreen.idc
new file mode 100644
index 0000000..2d4c26a
--- /dev/null
+++ b/Atmel_maXTouch_Touchscreen.idc
@@ -0,0 +1,25 @@
1# Copyright (C) 2010 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15#
16# Input Device Configuration File for the Atmel Maxtouch touch screen.
17#
18# These calibration values are derived from empirical measurements
19# and may not be appropriate for use with other touch screens.
20# Refer to the input device configuration documentation for more details.
21#
22
23# Basic Parameters
24touch.deviceType = touchScreen
25touch.orientationAware = 1
diff --git a/BoardConfig.mk b/BoardConfig.mk
new file mode 100644
index 0000000..ffc3bc0
--- /dev/null
+++ b/BoardConfig.mk
@@ -0,0 +1,80 @@
1#
2# Copyright (C) 2011 The Android Open-Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16
17# These two variables are set first, so they can be overridden
18# by BoardConfigVendor.mk
19BOARD_USES_GENERIC_AUDIO := true
20#USE_CAMERA_STUB := true
21#OMAP_ENHANCEMENT := true
22
23ifeq ($(OMAP_ENHANCEMENT),true)
24COMMON_GLOBAL_CFLAGS += -DOMAP_ENHANCEMENT
25# Multi-zone audio (requires ro.com.ti.omap_multizone_audio, see device.mk)
26#OMAP_MULTIZONE_AUDIO := true
27endif
28
29TARGET_CPU_ABI := armeabi-v7a
30TARGET_CPU_ABI2 := armeabi
31TARGET_CPU_SMP := true
32TARGET_ARCH := arm
33TARGET_ARCH_VARIANT := armv7-a-neon
34TARGET_CPU_VARIANT := cortex-a15
35
36BOARD_HAVE_BLUETOOTH := true
37BOARD_HAVE_BLUETOOTH_TI := true
38BOARD_BLUETOOTH_BDROID_BUILDCFG_INCLUDE_DIR := device/ti/jacinto6evm/bluetooth
39TARGET_NO_BOOTLOADER := true
40
41BOARD_KERNEL_BASE := 0x80000000
42#BOARD_KERNEL_CMDLINE := console=ttyO2,115200n8 mem=1024M androidboot.console=ttyO2 androidboot.hardware=jacinto6evmboard vram=20M omapfb.vram=0:16M
43BOARD_MKBOOTIMG_ARGS := --ramdisk_offset 0x01f00000
44
45TARGET_NO_RADIOIMAGE := true
46TARGET_BOARD_PLATFORM := jacinto6
47TARGET_BOOTLOADER_BOARD_NAME := jacinto6evm
48
49BOARD_EGL_CFG := device/ti/jacinto6evm/egl.cfg
50
51USE_OPENGL_RENDERER := true
52
53TARGET_USERIMAGES_USE_EXT4 := true
54BOARD_SYSTEMIMAGE_PARTITION_SIZE := 805306368
55BOARD_USERDATAIMAGE_PARTITION_SIZE := 2147483648
56BOARD_FLASH_BLOCK_SIZE := 4096
57
58TARGET_RECOVERY_FSTAB = device/ti/jacinto6evm/fstab.jacinto6evmboard
59TARGET_RECOVERY_PIXEL_FORMAT := "RGB565"
60TARGET_RELEASETOOLS_EXTENSIONS := device/ti/jacinto6evm
61
62# Connectivity - Wi-Fi
63#USES_TI_MAC80211 := true
64ifeq ($(USES_TI_MAC80211),true)
65BOARD_WPA_SUPPLICANT_DRIVER := NL80211
66WPA_SUPPLICANT_VERSION := VER_0_8_X_TI
67BOARD_HOSTAPD_DRIVER := NL80211
68BOARD_WLAN_DEVICE := wl12xx_mac80211
69BOARD_SOFTAP_DEVICE := wl12xx_mac80211
70COMMON_GLOBAL_CFLAGS += -DUSES_TI_MAC80211
71endif
72
73ifeq ($(OMAP_MULTIZONE_AUDIO),true)
74COMMON_GLOBAL_CFLAGS += -DOMAP_MULTIZONE_AUDIO
75endif
76
77#BOARD_SEPOLICY_DIRS := device/ti/jacinto6evm/sepolicy
78#BOARD_SEPOLICY_UNION := \
79# healthd.te
80
diff --git a/CleanSpec.mk b/CleanSpec.mk
new file mode 100644
index 0000000..07f668f
--- /dev/null
+++ b/CleanSpec.mk
@@ -0,0 +1,51 @@
1# Copyright (C) 2007 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14#
15
16# If you don't need to do a full clean build but would like to touch
17# a file or delete some intermediate files, add a clean step to the end
18# of the list. These steps will only be run once, if they haven't been
19# run before.
20#
21# E.g.:
22# $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
23# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
24#
25# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
26# files that are missing or have been moved.
27#
28# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
29# Use $(OUT_DIR) to refer to the "out" directory.
30#
31# If you need to re-do something that's already mentioned, just copy
32# the command and add it to the bottom of the list. E.g., if a change
33# that you made last week required touching a file and a change you
34# made today requires touching the same file, just copy the old
35# touch step and add it to the end of the list.
36#
37# ************************************************
38# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
39# ************************************************
40
41# For example:
42#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
43#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
44#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
45#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
46
47# ************************************************
48# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
49# ************************************************
50$(call add-clean-step, rm -f $(PRODUCT_OUT)/system/build.prop)
51$(call add-clean-step, rm -f $(PRODUCT_OUT)/system/build.prop) \ No newline at end of file
diff --git a/LDC_3001_TouchScreen_Controller.idc b/LDC_3001_TouchScreen_Controller.idc
new file mode 100644
index 0000000..2d4c26a
--- /dev/null
+++ b/LDC_3001_TouchScreen_Controller.idc
@@ -0,0 +1,25 @@
1# Copyright (C) 2010 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15#
16# Input Device Configuration File for the Atmel Maxtouch touch screen.
17#
18# These calibration values are derived from empirical measurements
19# and may not be appropriate for use with other touch screens.
20# Refer to the input device configuration documentation for more details.
21#
22
23# Basic Parameters
24touch.deviceType = touchScreen
25touch.orientationAware = 1
diff --git a/audio/Android.mk b/audio/Android.mk
new file mode 100644
index 0000000..da7bcfe
--- /dev/null
+++ b/audio/Android.mk
@@ -0,0 +1,37 @@
1# Copyright (C) 2013 Texas Instruments
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15LOCAL_PATH := $(call my-dir)
16
17include $(CLEAR_VARS)
18LOCAL_MODULE := mixer_paths.xml
19LOCAL_MODULE_TAGS := optional
20LOCAL_MODULE_CLASS := ETC
21LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
22LOCAL_SRC_FILES := $(LOCAL_MODULE)
23include $(BUILD_PREBUILT)
24
25# build multizone audio if the OMAP_MULTIZONE_AUDIO flag is set to true
26ifeq ($(OMAP_MULTIZONE_AUDIO),true)
27include $(CLEAR_VARS)
28
29include $(LOCAL_PATH)/multizone/Android.mk
30
31else # build the legacy audio if the OMAP_MULTIZONE_AUDIO flag is set to false
32
33include $(CLEAR_VARS)
34
35include $(LOCAL_PATH)/legacy/Android.mk
36
37endif
diff --git a/audio/legacy/Android.mk b/audio/legacy/Android.mk
new file mode 100644
index 0000000..1e6c223
--- /dev/null
+++ b/audio/legacy/Android.mk
@@ -0,0 +1,51 @@
1# Copyright (C) 2013 Texas Instruments
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15LOCAL_PATH := $(call my-dir)
16
17ifeq ($(findstring jacinto6, $(TARGET_BOARD_PLATFORM)),jacinto6)
18
19include $(CLEAR_VARS)
20LOCAL_MODULE := audio_policy.conf
21LOCAL_MODULE_TAGS := optional
22LOCAL_MODULE_CLASS := ETC
23LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
24LOCAL_SRC_FILES := $(LOCAL_MODULE)
25include $(BUILD_PREBUILT)
26
27include $(CLEAR_VARS)
28
29LOCAL_MODULE := audio.primary.$(TARGET_BOARD_PLATFORM)
30
31LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
32LOCAL_SRC_FILES := audio_hw.c
33
34LOCAL_C_INCLUDES += \
35 external/tinyalsa/include \
36 system/media/audio_route/include \
37 system/media/audio_utils/include \
38 system/media/audio_effects/include
39
40LOCAL_SHARED_LIBRARIES := \
41 liblog \
42 libcutils \
43 libtinyalsa \
44 libaudioroute \
45 libaudioutils
46
47LOCAL_MODULE_TAGS := optional
48
49include $(BUILD_SHARED_LIBRARY)
50
51endif
diff --git a/audio/legacy/audio_hw.c b/audio/legacy/audio_hw.c
new file mode 100644
index 0000000..772f17b
--- /dev/null
+++ b/audio/legacy/audio_hw.c
@@ -0,0 +1,1674 @@
1/*
2 * Copyright (C) 2013 Texas Instruments
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "audio_hw_primary"
18//#define LOG_NDEBUG 0
19//#define VERY_VERBOSE_LOGGING
20#ifdef VERY_VERBOSE_LOGGING
21#define ALOGVV ALOGV
22#else
23#define ALOGVV(a...) do { } while(0)
24#endif
25
26#include <errno.h>
27#include <stdint.h>
28#include <stdlib.h>
29#include <sys/time.h>
30
31#include <cutils/log.h>
32#include <cutils/str_parms.h>
33#include <cutils/properties.h>
34
35#include <audio_utils/resampler.h>
36#include <audio_route/audio_route.h>
37#include <system/audio.h>
38#include <hardware/hardware.h>
39#include <hardware/audio.h>
40#include <hardware/audio_effect.h>
41
42#include <tinyalsa/asoundlib.h>
43
44/* yet another definition of ARRAY_SIZE macro) */
45#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
46
47/*
48 * additional space in resampler buffer allowing for extra samples to be returned
49 * by speex resampler when sample rates ratio is not an integer
50 */
51#define RESAMPLER_HEADROOM_FRAMES 10
52
53/* buffer_remix: functor for doing in-place buffer manipulations.
54 *
55 * NB. When remix_func is called, the memory at `buf` must be at least
56 * as large as frames * sample_size * MAX(in_chans, out_chans).
57 */
58struct buffer_remix {
59 void (*remix_func)(struct buffer_remix *data, void *buf, size_t frames);
60 size_t sample_size; /* size of one audio sample, in bytes */
61 size_t in_chans; /* number of input channels */
62 size_t out_chans; /* number of output channels */
63};
64
65struct j6_voice_stream {
66 struct j6_audio_device *dev;
67 struct pcm *pcm_in;
68 struct pcm *pcm_out;
69 struct pcm_config in_config;
70 struct pcm_config out_config;
71 struct resampler_itfe *resampler;
72 struct resampler_buffer_provider buf_provider;
73 struct buffer_remix *remix;
74 pthread_t thread;
75 int16_t *in_buffer;
76 int16_t *out_buffer;
77 size_t in_frames;
78 size_t out_frames;
79 size_t frame_size;
80 char *name;
81};
82
83struct j6_voice {
84 struct j6_voice_stream ul;
85 struct j6_voice_stream dl;
86};
87
88struct j6_audio_device {
89 struct audio_hw_device device;
90 struct j6_stream_in *in;
91 struct j6_stream_out *out;
92 struct j6_voice voice;
93 struct audio_route *route;
94 audio_devices_t in_device;
95 audio_devices_t out_device;
96 pthread_mutex_t lock;
97 unsigned int card;
98 unsigned int in_port;
99 unsigned int out_port;
100 unsigned int bt_port;
101 bool mic_mute;
102 bool in_call;
103 audio_mode_t mode;
104};
105
106struct j6_stream_in {
107 struct audio_stream_in stream;
108 struct j6_audio_device *dev;
109 struct pcm_config config;
110 struct pcm *pcm;
111 struct buffer_remix *remix; /* adapt hw chan count to client */
112 struct resampler_itfe *resampler;
113 struct resampler_buffer_provider buf_provider;
114 int16_t *buffer;
115 size_t frames_in;
116 size_t hw_frame_size;
117 unsigned int requested_rate;
118 unsigned int requested_channels;
119 int read_status;
120 pthread_mutex_t lock;
121 bool standby;
122};
123
124struct j6_stream_out {
125 struct audio_stream_out stream;
126 struct j6_audio_device *dev;
127 struct pcm_config config;
128 struct pcm *pcm;
129 struct timespec last;
130 pthread_mutex_t lock;
131 bool standby;
132 int64_t written; /* total frames written, not cleared when entering standby */
133};
134
135
136static const char *supported_cards[] = {
137 "dra7evm",
138 "VayuEVM",
139};
140
141#define SUPPORTED_IN_DEVICES (AUDIO_DEVICE_IN_BUILTIN_MIC | \
142 AUDIO_DEVICE_IN_WIRED_HEADSET | \
143 AUDIO_DEVICE_IN_DEFAULT)
144#define SUPPORTED_OUT_DEVICES (AUDIO_DEVICE_OUT_SPEAKER | \
145 AUDIO_DEVICE_OUT_WIRED_HEADSET | \
146 AUDIO_DEVICE_OUT_WIRED_HEADPHONE | \
147 AUDIO_DEVICE_OUT_DEFAULT)
148
149#define CAPTURE_SAMPLE_RATE 44100
150#define CAPTURE_PERIOD_SIZE 960
151#define CAPTURE_PERIOD_COUNT 4
152#define CAPTURE_BUFFER_SIZE (CAPTURE_PERIOD_SIZE * CAPTURE_PERIOD_COUNT)
153
154#define PLAYBACK_SAMPLE_RATE 44100
155#define PLAYBACK_PERIOD_SIZE 960
156#define PLAYBACK_PERIOD_COUNT 4
157#define PLAYBACK_BUFFER_SIZE (PLAYBACK_PERIOD_SIZE * PLAYBACK_PERIOD_COUNT)
158
159#define BT_SAMPLE_RATE 8000
160#define BT_PERIOD_SIZE 160
161#define BT_PERIOD_COUNT 4
162#define BT_BUFFER_SIZE (BT_PERIOD_SIZE * BT_PERIOD_COUNT)
163
164struct pcm_config pcm_config_capture = {
165 .channels = 2,
166 .rate = CAPTURE_SAMPLE_RATE,
167 .format = PCM_FORMAT_S16_LE,
168 .period_size = CAPTURE_PERIOD_SIZE,
169 .period_count = CAPTURE_PERIOD_COUNT,
170 .start_threshold = 1,
171 .stop_threshold = CAPTURE_BUFFER_SIZE,
172};
173
174struct pcm_config pcm_config_playback = {
175 .channels = 2,
176 .rate = PLAYBACK_SAMPLE_RATE,
177 .format = PCM_FORMAT_S16_LE,
178 .period_size = PLAYBACK_PERIOD_SIZE,
179 .period_count = PLAYBACK_PERIOD_COUNT,
180 .start_threshold = PLAYBACK_BUFFER_SIZE / 2,
181 .stop_threshold = PLAYBACK_BUFFER_SIZE,
182 .avail_min = PLAYBACK_PERIOD_SIZE,
183};
184
185struct pcm_config pcm_config_bt_in = {
186 .channels = 2,
187 .rate = BT_SAMPLE_RATE,
188 .format = PCM_FORMAT_S16_LE,
189 .period_size = BT_PERIOD_SIZE,
190 .period_count = BT_PERIOD_COUNT,
191 .start_threshold = 1,
192 .stop_threshold = BT_BUFFER_SIZE,
193};
194
195struct pcm_config pcm_config_bt_out = {
196 .channels = 2,
197 .rate = BT_SAMPLE_RATE,
198 .format = PCM_FORMAT_S16_LE,
199 .period_size = BT_PERIOD_SIZE,
200 .period_count = BT_PERIOD_COUNT,
201 .start_threshold = BT_BUFFER_SIZE / 2,
202 .stop_threshold = BT_BUFFER_SIZE,
203 .avail_min = BT_PERIOD_SIZE,
204};
205
206static int find_supported_card(void)
207{
208 char name[256] = "";
209 int card = 0;
210 int found = 0;
211 unsigned int i;
212
213#ifdef OMAP_ENHANCEMENT
214 do {
215 /* returns an error after last valid card */
216 int ret = mixer_get_card_name(card, name, sizeof(name));
217 if (ret)
218 break;
219
220 for (i = 0; i < ARRAY_SIZE(supported_cards); ++i) {
221 if (supported_cards[i] && !strcmp(name, supported_cards[i])) {
222 ALOGV("Supported card '%s' found at %d", name, card);
223 found = 1;
224 break;
225 }
226 }
227 } while (!found && (card++ < MAX_CARD_COUNT));
228#endif
229
230 /* Use default card number if not found */
231 if (!found)
232 card = 0;
233
234 return card;
235}
236
237static void do_out_standby(struct j6_stream_out *out);
238
239/* must be called with device lock held */
240static void select_input_device(struct j6_audio_device *adev)
241{
242 if (adev->in_device & ~SUPPORTED_IN_DEVICES)
243 ALOGW("select_input_device() device not supported, will use default device");
244}
245
246/* must be called with device lock held */
247static void select_output_device(struct j6_audio_device *adev)
248{
249 if (adev->out_device & ~SUPPORTED_OUT_DEVICES)
250 ALOGW("select_output_device() device(s) not supported, will use default devices");
251}
252
253static size_t get_input_buffer_size(uint32_t sample_rate, int format, int channel_count)
254{
255 size_t size;
256
257 /*
258 * take resampling into account and return the closest majoring
259 * multiple of 16 frames, as audioflinger expects audio buffers to
260 * be a multiple of 16 frames
261 */
262 size = (pcm_config_capture.period_size * sample_rate) / pcm_config_capture.rate;
263 size = ((size + 15) / 16) * 16;
264
265 return size * channel_count * sizeof(int16_t);
266}
267
268/*
269 * Implementation of buffer_remix::remix_func that removes
270 * channels in place without doing any other processing. The
271 * extra channels are truncated.
272 */
273static void remove_channels_from_buf(struct buffer_remix *data, void *buf, size_t frames)
274{
275 size_t samp_size, in_frame, out_frame;
276 size_t N, c;
277 char *s, *d;
278
279 ALOGVV("remove_channels_from_buf() remix=%p buf=%p frames=%u",
280 data, buf, frames);
281
282 if (frames == 0)
283 return;
284
285 samp_size = data->sample_size;
286 in_frame = data->in_chans * samp_size;
287 out_frame = data->out_chans * samp_size;
288
289 if (out_frame >= in_frame) {
290 ALOGE("BUG: remove_channels_from_buf() can not add channels to a buffer.\n");
291 return;
292 }
293
294 N = frames - 1;
295 d = (char*)buf + out_frame;
296 s = (char*)buf + in_frame;
297
298 /* take the first several channels and truncate the rest */
299 while (N--) {
300 for (c = 0; c < out_frame; ++c)
301 d[c] = s[c];
302 d += out_frame;
303 s += in_frame;
304 }
305}
306
307static int setup_stereo_to_mono_input_remix(struct j6_stream_in *in)
308{
309 ALOGV("setup_stereo_to_mono_input_remix() stream=%p", in);
310
311 struct buffer_remix *br = (struct buffer_remix *)malloc(sizeof(struct buffer_remix));
312 if (!br)
313 return -ENOMEM;
314
315 br->remix_func = remove_channels_from_buf;
316 br->sample_size = sizeof(int16_t);
317 br->in_chans = 2;
318 br->out_chans = 1;
319 in->remix = br;
320
321 return 0;
322}
323
324/*
325 * Implementation of buffer_remix::remix_func that duplicates the first
326 * channel into the rest of channels in the frame without doing any other
327 * processing. It assumes data in 16-bits, but it's not explicitly checked
328 */
329static void mono_remix(struct buffer_remix *data, void *buf, size_t frames)
330{
331 int16_t *buffer = (int16_t*)buf;
332 size_t i;
333
334 ALOGVV("mono_remix() remix=%p buf=%p frames=%u", data, buf, frames);
335
336 if (frames == 0)
337 return;
338
339 /* duplicate first channel into the rest of channels in the frame */
340 while (frames--) {
341 for (i = 1; i < data->out_chans; i++)
342 buffer[i] = buffer[0];
343 buffer += data->out_chans;
344 }
345}
346
347static int setup_mono_input_remix(struct j6_voice_stream *stream)
348{
349 ALOGV("setup_mono_input_remix() %s stream", stream->name);
350
351 struct buffer_remix *br = (struct buffer_remix *)malloc(sizeof(struct buffer_remix));
352 if (!br)
353 return -ENOMEM;
354
355 br->remix_func = mono_remix;
356 br->sample_size = sizeof(int16_t);
357 br->in_chans = stream->in_config.channels;
358 br->out_chans = stream->out_config.channels;
359 stream->remix = br;
360
361 return 0;
362}
363
364static int voice_get_next_buffer(struct resampler_buffer_provider *buffer_provider,
365 struct resampler_buffer* buffer)
366{
367 struct j6_voice_stream *stream;
368 int ret;
369
370 if (buffer_provider == NULL || buffer == NULL) {
371 ALOGE("voice_get_next_buffer() invalid buffer/provider");
372 return -EINVAL;
373 }
374
375 stream = (struct j6_voice_stream *)((char *)buffer_provider -
376 offsetof(struct j6_voice_stream, buf_provider));
377
378 if (stream->pcm_in == NULL) {
379 buffer->raw = NULL;
380 buffer->frame_count = 0;
381 return -ENODEV;
382 }
383
384 if (buffer->frame_count > stream->in_frames) {
385 ALOGW("voice_get_next_buffer() %s unexpected frame count %u, "
386 "buffer was allocated for %u frames",
387 stream->name, buffer->frame_count, stream->in_frames);
388 buffer->frame_count = stream->in_frames;
389 }
390
391 ret = pcm_read(stream->pcm_in, stream->in_buffer,
392 buffer->frame_count * stream->frame_size);
393 if (ret) {
394 ALOGE("voice_get_next_buffer() failed to read %s: %s",
395 stream->name, pcm_get_error(stream->pcm_in));
396 buffer->raw = NULL;
397 buffer->frame_count = 0;
398 return ret;
399 }
400
401 buffer->i16 = stream->in_buffer;
402
403 return ret;
404}
405
406static void voice_release_buffer(struct resampler_buffer_provider *buffer_provider,
407 struct resampler_buffer* buffer)
408{
409}
410
411static void *voice_thread_func(void *arg)
412{
413 struct j6_voice_stream *stream = (struct j6_voice_stream *)arg;
414 struct j6_audio_device *adev = stream->dev;
415 struct timespec now;
416 size_t frames = stream->out_frames;
417 uint32_t periods = 0;
418 uint32_t avail;
419 bool in_steady = false;
420 bool out_steady = false;
421 int ret = 0;
422
423 pcm_start(stream->pcm_in);
424
425 memset(stream->out_buffer, 0, stream->out_frames * stream->frame_size);
426
427 while (adev->in_call) {
428 if (out_steady) {
429 if (in_steady) {
430 stream->resampler->resample_from_provider(stream->resampler,
431 stream->out_buffer,
432 &frames);
433 } else {
434 ret = pcm_get_htimestamp(stream->pcm_in, &avail, &now);
435 if (!ret && (avail > 0)) {
436 in_steady = true;
437 continue;
438 }
439 }
440 } else if (++periods == stream->out_config.period_count) {
441 out_steady = true;
442 }
443
444 if (stream->remix)
445 stream->remix->remix_func(stream->remix, stream->out_buffer, frames);
446
447 ret = pcm_write(stream->pcm_out, stream->out_buffer,
448 frames * stream->frame_size);
449 if (ret) {
450 ALOGE("voice_thread_func() failed to write %s: %s",
451 stream->name, pcm_get_error(stream->pcm_out));
452 usleep((frames * 1000000) / stream->out_config.rate);
453 }
454 }
455
456 return (void*)ret;
457}
458
459static void voice_stream_exit(struct j6_voice_stream *stream)
460{
461 if (stream->resampler) {
462 release_resampler(stream->resampler);
463 stream->resampler = NULL;
464 }
465
466 if (stream->pcm_out) {
467 pcm_close(stream->pcm_out);
468 stream->pcm_out = NULL;
469 }
470
471 if (stream->pcm_in) {
472 pcm_close(stream->pcm_in);
473 stream->pcm_in = NULL;
474 }
475
476 if (stream->in_buffer) {
477 free(stream->in_buffer);
478 stream->in_buffer = NULL;
479 stream->in_frames = 0;
480 }
481
482 if (stream->out_buffer) {
483 free(stream->out_buffer);
484 stream->out_buffer = NULL;
485 stream->out_frames = 0;
486 }
487
488 if (stream->remix) {
489 free(stream->remix);
490 stream->remix = NULL;
491 }
492
493 if (stream->name) {
494 free(stream->name);
495 stream->name = NULL;
496 }
497}
498
499static int voice_stream_init(struct j6_voice_stream *stream,
500 unsigned int in_port,
501 unsigned int out_port,
502 bool needs_mono_remix)
503{
504 struct j6_audio_device *adev = stream->dev;
505 int ret;
506
507 stream->buf_provider.get_next_buffer = voice_get_next_buffer;
508 stream->buf_provider.release_buffer = voice_release_buffer;
509 ret = create_resampler(stream->in_config.rate,
510 stream->out_config.rate,
511 2,
512 RESAMPLER_QUALITY_DEFAULT,
513 &stream->buf_provider,
514 &stream->resampler);
515 if (ret) {
516 ALOGE("voice_stream_init() failed to create %s resampler %d", stream->name, ret);
517 return ret;
518 }
519
520 stream->pcm_in = pcm_open(adev->card, in_port, PCM_IN, &stream->in_config);
521 stream->pcm_out = pcm_open(adev->card, out_port, PCM_OUT, &stream->out_config);
522
523 if (!pcm_is_ready(stream->pcm_in) || !pcm_is_ready(stream->pcm_out)) {
524 ALOGE("voice_stream_init() failed to open pcm %s devices", stream->name);
525 voice_stream_exit(stream);
526 return -ENODEV;
527 }
528
529 stream->frame_size = pcm_frames_to_bytes(stream->pcm_in, 1);
530
531 /* out_buffer will store the resampled data */
532 stream->out_frames = stream->out_config.period_size;
533 stream->out_buffer = malloc(stream->out_frames * stream->frame_size);
534
535 /* in_buffer will store the frames recorded from the PCM device */
536 stream->in_frames = (stream->out_frames * stream->in_config.rate) / stream->out_config.rate +
537 RESAMPLER_HEADROOM_FRAMES;
538 stream->in_buffer = malloc(stream->in_frames * stream->frame_size);
539
540 if (!stream->in_buffer || !stream->out_buffer) {
541 ALOGE("voice_stream_init() failed to allocate %s buffers", stream->name);
542 voice_stream_exit(stream);
543 return -ENOMEM;
544 }
545
546 if (needs_mono_remix) {
547 ret = setup_mono_input_remix(stream);
548 if (ret) {
549 ALOGE("voice_stream_init() failed to setup mono remix %d", ret);
550 voice_stream_exit(stream);
551 return ret;
552 }
553 } else {
554 stream->remix = NULL;
555 }
556
557 return 0;
558}
559
560static int enter_voice_call(struct j6_audio_device *adev)
561{
562 struct j6_voice *voice = &adev->voice;
563 int ret;
564
565 ALOGI("enter_voice_call() entering bluetooth voice call");
566
567 audio_route_apply_path(adev->route, "BT SCO Master");
568 audio_route_update_mixer(adev->route);
569
570 /* Let the primary output switch to a dummy sink */
571 if (adev->out)
572 do_out_standby(adev->out);
573
574 /* Uplink: Mic (44.1kHz) -> BT (8kHz) */
575 voice->ul.name = strdup("UL");
576 voice->ul.in_config = pcm_config_capture;
577 voice->ul.out_config = pcm_config_bt_out;
578 voice->ul.dev = adev;
579 ret = voice_stream_init(&voice->ul, adev->in_port, adev->bt_port, false);
580 if (ret) {
581 ALOGE("enter_voice_call() failed to init uplink %d", ret);
582 goto err_ul_init;
583 }
584
585 /* Downlink: BT (8kHz) -> HP/Spk (44.1kHz) */
586 voice->dl.name = strdup("DL");
587 voice->dl.in_config = pcm_config_bt_in;
588 voice->dl.out_config = pcm_config_playback;
589 voice->dl.dev = adev;
590 ret = voice_stream_init(&voice->dl, adev->bt_port, adev->out_port, true);
591 if (ret) {
592 ALOGE("enter_voice_call() failed to init downlink %d", ret);
593 goto err_dl_init;
594 }
595
596 adev->in_call = true;
597
598 /* Create uplink thread: Mic -> BT */
599 ret = pthread_create(&voice->ul.thread, NULL, voice_thread_func, &voice->ul);
600 if (ret) {
601 ALOGE("enter_voice_call() failed to create uplink thread %d", ret);
602 adev->in_call = false;
603 goto err_ul_thread;
604 }
605
606 /* Create downlink thread: BT -> HP/Spk */
607 ret = pthread_create(&voice->dl.thread, NULL, voice_thread_func, &voice->dl);
608 if (ret) {
609 ALOGE("enter_voice_call() failed to create downlink thread %d", ret);
610 adev->in_call = false;
611 goto err_dl_thread;
612 }
613
614 return 0;
615
616 err_dl_thread:
617 pthread_join(voice->ul.thread, NULL);
618 err_ul_thread:
619 voice_stream_exit(&voice->ul);
620 err_dl_init:
621 voice_stream_exit(&voice->dl);
622 err_ul_init:
623 audio_route_reset_path(adev->route, "BT SCO Master");
624 audio_route_update_mixer(adev->route);
625
626 return ret;
627}
628
629static void leave_voice_call(struct j6_audio_device *adev)
630{
631 struct j6_voice *voice = &adev->voice;
632 struct j6_voice_stream *ul = &voice->ul;
633 struct j6_voice_stream *dl = &voice->dl;
634 void *ret;
635
636 ALOGI("leave_voice_call() leaving bluetooth voice call");
637
638 adev->in_call = false;
639
640 /*
641 * The PCM ports used for Bluetooth are slaves and they can lose the
642 * BCLK and FSYNC while still active. That leads to blocking read() and
643 * write() calls, which is prevented by switching the clock source to
644 * an internal one and explicitly stopping both ports for the new source
645 * to take effect at kernel level
646 */
647 audio_route_reset_path(adev->route, "BT SCO Master");
648 audio_route_update_mixer(adev->route);
649 if (ul->pcm_out)
650 pcm_stop(ul->pcm_out);
651 if (dl->pcm_in)
652 pcm_stop(dl->pcm_in);
653
654 pthread_join(voice->dl.thread, &ret);
655 pthread_join(voice->ul.thread, &ret);
656
657 voice_stream_exit(&voice->dl);
658 voice_stream_exit(&voice->ul);
659
660 /* Let the primary output switch back to its ALSA PCM device */
661 if (adev->out)
662 do_out_standby(adev->out);
663}
664
665static uint32_t time_diff(struct timespec t1, struct timespec t0)
666{
667 struct timespec temp;
668
669 if ((t1.tv_nsec - t0.tv_nsec) < 0) {
670 temp.tv_sec = t1.tv_sec - t0.tv_sec-1;
671 temp.tv_nsec = 1000000000UL + t1.tv_nsec - t0.tv_nsec;
672 } else {
673 temp.tv_sec = t1.tv_sec - t0.tv_sec;
674 temp.tv_nsec = t1.tv_nsec - t0.tv_nsec;
675 }
676
677 return (temp.tv_sec * 1000000UL + temp.tv_nsec / 1000);
678}
679
680/* audio HAL functions */
681
682static uint32_t out_get_sample_rate(const struct audio_stream *stream)
683{
684 uint32_t rate = PLAYBACK_SAMPLE_RATE;
685
686 ALOGVV("out_get_sample_rate() stream=%p rate=%u", stream, rate);
687
688 return rate;
689}
690
691static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
692{
693 ALOGVV("out_set_sample_rate() stream=%p rate=%u", stream, rate);
694
695 return 0;
696}
697
698static size_t out_get_buffer_size(const struct audio_stream *stream)
699{
700 uint32_t frames = ((PLAYBACK_PERIOD_SIZE + 15) / 16) * 16;
701 size_t bytes = frames * audio_stream_frame_size(stream);
702
703 ALOGVV("out_get_buffer_size() stream=%p frames=%u bytes=%u", stream, frames, bytes);
704
705 return bytes;
706}
707
708static audio_channel_mask_t out_get_channels(const struct audio_stream *stream)
709{
710 audio_channel_mask_t channels = AUDIO_CHANNEL_OUT_STEREO;
711
712 ALOGVV("out_get_channels() stream=%p channels=%u", stream, popcount(channels));
713
714 return channels;
715}
716
717static audio_format_t out_get_format(const struct audio_stream *stream)
718{
719 audio_format_t format = AUDIO_FORMAT_PCM_16_BIT;
720
721 ALOGVV("out_set_format() stream=%p format=0x%08x (%u bits/sample)",
722 stream, format, audio_bytes_per_sample(format) << 3);
723
724 return format;
725}
726
727static int out_set_format(struct audio_stream *stream, audio_format_t format)
728{
729 ALOGVV("out_set_format() stream=%p format=0x%08x (%u bits/sample)",
730 stream, format, audio_bytes_per_sample(format) << 3);
731
732 if (format != AUDIO_FORMAT_PCM_16_BIT) {
733 return -ENOSYS;
734 } else {
735 return 0;
736 }
737}
738
739/* must be called with locks held */
740static void do_out_standby(struct j6_stream_out *out)
741{
742 struct j6_audio_device *adev = out->dev;
743
744 if (!out->standby) {
745 if (adev->mode != AUDIO_MODE_IN_CALL) {
746 ALOGI("do_out_standby() close card %u port %u", adev->card, adev->out_port);
747 pcm_close(out->pcm);
748 out->pcm = NULL;
749 } else {
750 ALOGI("do_out_standby() close dummy card");
751 }
752 out->standby = true;
753 }
754}
755
756static int out_standby(struct audio_stream *stream)
757{
758 struct j6_stream_out *out = (struct j6_stream_out *)(stream);
759 struct j6_audio_device *adev = out->dev;
760
761 ALOGV("out_standby() stream=%p", out);
762 pthread_mutex_lock(&adev->lock);
763 pthread_mutex_lock(&out->lock);
764 do_out_standby(out);
765 pthread_mutex_unlock(&out->lock);
766 pthread_mutex_unlock(&adev->lock);
767
768 return 0;
769}
770
771static int out_dump(const struct audio_stream *stream, int fd)
772{
773 return 0;
774}
775
776static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
777{
778 struct j6_stream_out *out = (struct j6_stream_out *)(stream);
779 struct j6_audio_device *adev = out->dev;
780 struct str_parms *parms;
781 char value[32];
782 int ret;
783 uint32_t val = 0;
784
785 ALOGV("out_set_parameters() stream=%p parameter='%s'", out, kvpairs);
786
787 parms = str_parms_create_str(kvpairs);
788
789 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
790 if (ret >= 0) {
791 val = atoi(value);
792 pthread_mutex_lock(&adev->lock);
793 pthread_mutex_lock(&out->lock);
794 if (val != 0) {
795 if ((adev->out_device & AUDIO_DEVICE_OUT_ALL) != val)
796 do_out_standby(out);
797
798 /* set the active output device */
799 adev->out_device = val;
800 select_output_device(adev);
801 }
802 pthread_mutex_unlock(&out->lock);
803 pthread_mutex_unlock(&adev->lock);
804 }
805
806 return 0;
807}
808
809static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
810{
811 return strdup("");
812}
813
814static uint32_t out_get_latency(const struct audio_stream_out *stream)
815{
816 const struct j6_stream_out *out = (const struct j6_stream_out *)(stream);
817 uint32_t frames = PLAYBACK_BUFFER_SIZE;
818 uint32_t latency = (frames * 1000) / PLAYBACK_SAMPLE_RATE;
819
820 ALOGVV("out_get_latency() stream=%p latency=%u msecs", out, latency);
821
822 return latency;
823}
824
825static int out_set_volume(struct audio_stream_out *stream, float left,
826 float right)
827{
828 return -ENOSYS;
829}
830
831static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
832 size_t bytes)
833{
834 struct j6_stream_out *out = (struct j6_stream_out *)(stream);
835 struct j6_audio_device *adev = out->dev;
836 struct timespec now;
837 const size_t frame_size = audio_stream_frame_size(&stream->common);
838 const size_t frames = bytes / frame_size;
839 uint32_t rate = out->config.rate;
840 uint32_t write_usecs = frames * 1000000 / rate;
841 uint32_t diff_usecs;
842 int ret = 0;
843
844 ALOGVV("out_write() stream=%p buffer=%p size=%u/%u time=%u usecs",
845 out, buffer, frames, rate, write_usecs);
846
847 pthread_mutex_lock(&adev->lock);
848 pthread_mutex_lock(&out->lock);
849
850 if (out->standby) {
851 if (!adev->in_call) {
852 select_output_device(adev);
853
854 ALOGI("out_write() open card %u port %u", adev->card, adev->out_port);
855 out->pcm = pcm_open(adev->card, adev->out_port, PCM_OUT, &out->config);
856 if (!pcm_is_ready(out->pcm)) {
857 ALOGE("out_write() failed to open pcm out: %s", pcm_get_error(out->pcm));
858 pcm_close(out->pcm);
859 out->pcm = NULL;
860 ret = -ENODEV;
861 }
862 } else {
863 ALOGI("out_write() open dummy port");
864 clock_gettime(CLOCK_REALTIME, &out->last);
865 }
866
867 if (ret) {
868 usleep(write_usecs); /* limits the rate of error messages */
869 pthread_mutex_unlock(&out->lock);
870 pthread_mutex_unlock(&adev->lock);
871 return ret;
872 }
873
874 out->standby = false;
875 }
876
877 pthread_mutex_unlock(&adev->lock);
878
879 if (!adev->in_call) {
880 ret = pcm_write(out->pcm, buffer, bytes);
881 if (ret) {
882 ALOGE("out_write() failed to write audio data %d", ret);
883 usleep(write_usecs); /* limits the rate of error messages */
884 }
885 } else {
886 clock_gettime(CLOCK_REALTIME, &now);
887 diff_usecs = time_diff(now, out->last);
888 if (write_usecs > diff_usecs)
889 usleep(write_usecs - diff_usecs);
890
891 clock_gettime(CLOCK_REALTIME, &out->last);
892 }
893
894 out->written += frames;
895
896 pthread_mutex_unlock(&out->lock);
897
898 return bytes;
899}
900
901static int out_get_render_position(const struct audio_stream_out *stream,
902 uint32_t *dsp_frames)
903{
904 return -EINVAL;
905}
906
907static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
908{
909 return 0;
910}
911
912static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
913{
914 return 0;
915}
916
917static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
918 int64_t *timestamp)
919{
920 return -EINVAL;
921}
922
923static int out_get_presentation_position(const struct audio_stream_out *stream,
924 uint64_t *frames, struct timespec *timestamp)
925{
926 struct j6_stream_out *out = (struct j6_stream_out *)(stream);
927 struct j6_audio_device *adev = out->dev;
928 int64_t signed_frames = -1;
929 size_t avail;
930 int ret = -1;
931
932 pthread_mutex_lock(&out->lock);
933
934 if (!adev->in_call) {
935 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
936 signed_frames = out->written - pcm_get_buffer_size(out->pcm) + avail;
937 }
938 } else {
939 clock_gettime(CLOCK_REALTIME, timestamp);
940 signed_frames = out->written +
941 (time_diff(*timestamp, out->last) * out->config.rate) / 1000000;
942 }
943
944 /* It would be unusual for this value to be negative, but check just in case ... */
945 if (signed_frames >= 0) {
946 *frames = signed_frames;
947 ret = 0;
948 }
949
950 pthread_mutex_unlock(&out->lock);
951
952 return ret;
953}
954
955/** audio_stream_in implementation **/
956static uint32_t in_get_sample_rate(const struct audio_stream *stream)
957{
958 const struct j6_stream_in *in = (const struct j6_stream_in *)(stream);
959
960 ALOGVV("in_get_sample_rate() stream=%p rate=%u", stream, in->requested_rate);
961
962 return in->requested_rate;
963}
964
965static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
966{
967 ALOGV("in_set_sample_rate() stream=%p rate=%u", stream, rate);
968
969 return 0;
970}
971
972static size_t in_get_buffer_size(const struct audio_stream *stream)
973{
974 const struct j6_stream_in *in = (const struct j6_stream_in *)(stream);
975
976 size_t bytes = get_input_buffer_size(in->requested_rate,
977 AUDIO_FORMAT_PCM_16_BIT,
978 in->requested_channels);
979
980 ALOGVV("in_get_buffer_size() stream=%p bytes=%u", in, bytes);
981
982 return bytes;
983}
984
985static audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
986{
987 const struct j6_stream_in *in = (const struct j6_stream_in *)(stream);
988 audio_channel_mask_t channels = audio_channel_out_mask_from_count(in->requested_channels);
989
990 ALOGVV("in_get_channels() stream=%p channels=%u", in, in->requested_channels);
991
992 return channels;
993}
994
995static audio_format_t in_get_format(const struct audio_stream *stream)
996{
997 audio_format_t format = AUDIO_FORMAT_PCM_16_BIT;
998
999 ALOGVV("in_set_format() stream=%p format=0x%08x (%u bits/sample)",
1000 stream, format, audio_bytes_per_sample(format) << 3);
1001
1002 return format;
1003}
1004
1005static int in_set_format(struct audio_stream *stream, audio_format_t format)
1006{
1007 ALOGV("in_set_format() stream=%p format=0x%08x (%u bits/sample)",
1008 stream, format, audio_bytes_per_sample(format) << 3);
1009
1010 if (format != AUDIO_FORMAT_PCM_16_BIT) {
1011 return -ENOSYS;
1012 } else {
1013 return 0;
1014 }
1015}
1016
1017/* must be called with locks held */
1018static void do_in_standby(struct j6_stream_in *in)
1019{
1020 struct j6_audio_device *adev = in->dev;
1021
1022 if (!in->standby) {
1023 ALOGI("do_in_standby() close card %u port %u", adev->card, adev->out_port);
1024 pcm_close(in->pcm);
1025 in->pcm = NULL;
1026 in->standby = true;
1027 }
1028}
1029
1030static int in_standby(struct audio_stream *stream)
1031{
1032 struct j6_stream_in *in = (struct j6_stream_in *)(stream);
1033 struct j6_audio_device *adev = in->dev;
1034
1035 ALOGV("in_standby() stream=%p", in);
1036 pthread_mutex_lock(&adev->lock);
1037 pthread_mutex_lock(&in->lock);
1038 do_in_standby(in);
1039 pthread_mutex_unlock(&in->lock);
1040 pthread_mutex_unlock(&adev->lock);
1041
1042 return 0;
1043}
1044
1045static int in_dump(const struct audio_stream *stream, int fd)
1046{
1047 return 0;
1048}
1049
1050static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
1051{
1052 struct j6_stream_in *in = (struct j6_stream_in *)(stream);
1053 struct j6_audio_device *adev = in->dev;
1054 struct str_parms *parms;
1055 char value[32];
1056 int ret;
1057 uint32_t val = 0;
1058
1059 ALOGV("in_set_parameters() stream=%p parameter='%s'", stream, kvpairs);
1060
1061 parms = str_parms_create_str(kvpairs);
1062
1063 /* Nothing to do for AUDIO_PARAMETER_STREAM_INPUT_SOURCE, so it's ignored */
1064
1065 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1066 if (ret >= 0) {
1067 val = atoi(value);
1068 pthread_mutex_lock(&adev->lock);
1069 pthread_mutex_lock(&in->lock);
1070 if (val != 0) {
1071 if ((adev->in_device & AUDIO_DEVICE_IN_ALL) != val)
1072 do_in_standby(in);
1073
1074 /* set the active input device */
1075 adev->in_device = val;
1076 select_input_device(adev);
1077 }
1078 pthread_mutex_unlock(&in->lock);
1079 pthread_mutex_unlock(&adev->lock);
1080 }
1081
1082 return 0;
1083}
1084
1085static char * in_get_parameters(const struct audio_stream *stream,
1086 const char *keys)
1087{
1088 return strdup("");
1089}
1090
1091static int in_set_gain(struct audio_stream_in *stream, float gain)
1092{
1093 return 0;
1094}
1095
1096static int get_next_buffer(struct resampler_buffer_provider *buffer_provider,
1097 struct resampler_buffer* buffer)
1098{
1099 struct j6_stream_in *in;
1100 struct buffer_remix *remix;
1101
1102 if (buffer_provider == NULL || buffer == NULL)
1103 return -EINVAL;
1104
1105 in = (struct j6_stream_in *)((char *)buffer_provider -
1106 offsetof(struct j6_stream_in, buf_provider));
1107
1108 if (in->pcm == NULL) {
1109 buffer->raw = NULL;
1110 buffer->frame_count = 0;
1111 in->read_status = -ENODEV;
1112 return -ENODEV;
1113 }
1114
1115 if (in->frames_in == 0) {
1116 in->read_status = pcm_read(in->pcm,
1117 (void*)in->buffer,
1118 buffer->frame_count * in->hw_frame_size);
1119 if (in->read_status != 0) {
1120 ALOGE("get_next_buffer() pcm_read error %d", in->read_status);
1121 buffer->raw = NULL;
1122 buffer->frame_count = 0;
1123 return in->read_status;
1124 }
1125 in->frames_in = buffer->frame_count;
1126
1127 remix = in->remix;
1128 if (remix)
1129 remix->remix_func(remix, in->buffer, in->frames_in);
1130 }
1131
1132 buffer->frame_count = (buffer->frame_count > in->frames_in) ?
1133 in->frames_in : buffer->frame_count;
1134 buffer->i16 = in->buffer;
1135
1136 return in->read_status;
1137}
1138
1139static void release_buffer(struct resampler_buffer_provider *buffer_provider,
1140 struct resampler_buffer* buffer)
1141{
1142 struct j6_stream_in *in;
1143
1144 if (buffer_provider == NULL || buffer == NULL)
1145 return;
1146
1147 in = (struct j6_stream_in *)((char *)buffer_provider -
1148 offsetof(struct j6_stream_in, buf_provider));
1149
1150 in->frames_in -= buffer->frame_count;
1151}
1152
1153/*
1154 * read_frames() reads frames from kernel driver, down samples to capture rate
1155 * if necessary and output the number of frames requested to the buffer specified
1156 */
1157static ssize_t read_frames(struct j6_stream_in *in, void *buffer, ssize_t frames)
1158{
1159 ssize_t frames_wr = 0;
1160 size_t frame_size;
1161
1162 ALOGVV("read_frames() stream=%p frames=%u", in, frames);
1163
1164 if (in->remix)
1165 frame_size = audio_stream_frame_size(&in->stream.common);
1166 else
1167 frame_size = in->hw_frame_size;
1168
1169 while (frames_wr < frames) {
1170 size_t frames_rd = frames - frames_wr;
1171
1172 in->resampler->resample_from_provider(in->resampler,
1173 (int16_t *)((char *)buffer + frames_wr * frame_size),
1174 &frames_rd);
1175 /* in->read_status is updated by getNextBuffer() also called by
1176 * in->resampler->resample_from_provider() */
1177 if (in->read_status != 0)
1178 return in->read_status;
1179
1180 frames_wr += frames_rd;
1181 }
1182
1183 return frames_wr;
1184}
1185
1186static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
1187 size_t bytes)
1188{
1189 struct j6_stream_in *in = (struct j6_stream_in *)(stream);
1190 struct j6_audio_device *adev = in->dev;
1191 const size_t frame_size = audio_stream_frame_size(&stream->common);
1192 const size_t frames = bytes / frame_size;
1193 uint32_t rate = in_get_sample_rate(&stream->common);
1194 uint32_t read_usecs = frames * 1000000 / rate;
1195 int ret;
1196
1197 ALOGVV("in_read() stream=%p buffer=%p size=%u/%u time=%u usecs",
1198 stream, buffer, frames, rate, read_usecs);
1199
1200 pthread_mutex_lock(&adev->lock);
1201 pthread_mutex_lock(&in->lock);
1202
1203 if (in->standby) {
1204 select_input_device(adev);
1205
1206 ALOGI("in_read() open card %u port %u", adev->card, adev->in_port);
1207 in->pcm = pcm_open(adev->card, adev->in_port, PCM_IN, &in->config);
1208 if (!pcm_is_ready(in->pcm)) {
1209 ALOGE("in_read() failed to open pcm in: %s", pcm_get_error(in->pcm));
1210 pcm_close(in->pcm);
1211 in->pcm = NULL;
1212 usleep(read_usecs); /* limits the rate of error messages */
1213 pthread_mutex_unlock(&in->lock);
1214 pthread_mutex_unlock(&adev->lock);
1215 return -ENODEV;
1216 }
1217
1218 /* if no supported sample rate is available, use the resampler */
1219 if (in->resampler) {
1220 in->resampler->reset(in->resampler);
1221 in->frames_in = 0;
1222 }
1223
1224 in->standby = false;
1225 }
1226
1227 pthread_mutex_unlock(&adev->lock);
1228
1229 if (in->resampler || in->remix)
1230 ret = read_frames(in, buffer, frames);
1231 else
1232 ret = pcm_read(in->pcm, buffer, bytes);
1233
1234 if (ret < 0) {
1235 ALOGE("in_read() failed to read audio data %d", ret);
1236 usleep(read_usecs); /* limits the rate of error messages */
1237 memset(buffer, 0, bytes);
1238 } else if (adev->mic_mute) {
1239 memset(buffer, 0, bytes);
1240 }
1241
1242 pthread_mutex_unlock(&in->lock);
1243
1244 return bytes;
1245}
1246
1247static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
1248{
1249 ALOGVV("in_get_input_frames_lost() stream=%p frames=%u", stream, 0);
1250 return 0;
1251}
1252
1253static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1254{
1255 return 0;
1256}
1257
1258static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1259{
1260 return 0;
1261}
1262
1263static int adev_open_output_stream(struct audio_hw_device *dev,
1264 audio_io_handle_t handle,
1265 audio_devices_t devices,
1266 audio_output_flags_t flags,
1267 struct audio_config *config,
1268 struct audio_stream_out **stream_out,
1269 const char *address __unused)
1270{
1271 struct j6_audio_device *adev = (struct j6_audio_device *)dev;
1272 struct j6_stream_out *out;
1273
1274 out = (struct j6_stream_out *)malloc(sizeof(struct j6_stream_out));
1275 if (!out)
1276 return -ENOMEM;
1277
1278 ALOGV("adev_open_output_stream() stream=%p rate=%u channels=%u "
1279 "format=0x%08x flags=0x%08x",
1280 out, config->sample_rate, popcount(config->channel_mask),
1281 config->format, flags);
1282
1283 pthread_mutex_init(&out->lock, NULL);
1284
1285 out->stream.common.get_sample_rate = out_get_sample_rate;
1286 out->stream.common.set_sample_rate = out_set_sample_rate;
1287 out->stream.common.get_buffer_size = out_get_buffer_size;
1288 out->stream.common.get_channels = out_get_channels;
1289 out->stream.common.get_format = out_get_format;
1290 out->stream.common.set_format = out_set_format;
1291 out->stream.common.standby = out_standby;
1292 out->stream.common.dump = out_dump;
1293 out->stream.common.set_parameters = out_set_parameters;
1294 out->stream.common.get_parameters = out_get_parameters;
1295 out->stream.common.add_audio_effect = out_add_audio_effect;
1296 out->stream.common.remove_audio_effect = out_remove_audio_effect;
1297 out->stream.get_latency = out_get_latency;
1298 out->stream.set_volume = out_set_volume;
1299 out->stream.write = out_write;
1300 out->stream.get_render_position = out_get_render_position;
1301 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
1302 out->stream.get_presentation_position = out_get_presentation_position;
1303
1304 out->dev = adev;
1305 out->standby = true;
1306 out->config = pcm_config_playback;
1307 out->written = 0;
1308 adev->out = out;
1309
1310 config->format = out_get_format(&out->stream.common);
1311 config->channel_mask = out_get_channels(&out->stream.common);
1312 config->sample_rate = out_get_sample_rate(&out->stream.common);
1313
1314 *stream_out = &out->stream;
1315
1316 return 0;
1317}
1318
1319static void adev_close_output_stream(struct audio_hw_device *dev,
1320 struct audio_stream_out *stream)
1321{
1322 struct j6_audio_device *adev = (struct j6_audio_device *)dev;
1323 struct j6_stream_out *out = (struct j6_stream_out *)(stream);
1324
1325 ALOGV("adev_close_output_stream() stream=%p", out);
1326
1327 out_standby(&stream->common);
1328 out->dev = NULL;
1329 adev->out = NULL;
1330
1331 free(stream);
1332}
1333
1334static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
1335{
1336 return -ENOSYS;
1337}
1338
1339static char * adev_get_parameters(const struct audio_hw_device *dev,
1340 const char *keys)
1341{
1342 return strdup("");;
1343}
1344
1345static int adev_init_check(const struct audio_hw_device *dev)
1346{
1347 return 0;
1348}
1349
1350static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
1351{
1352 return -ENOSYS;
1353}
1354
1355static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
1356{
1357 return -ENOSYS;
1358}
1359
1360static int adev_get_master_volume(struct audio_hw_device *dev, float *volume)
1361{
1362 return -ENOSYS;
1363}
1364
1365static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
1366{
1367 return -ENOSYS;
1368}
1369
1370static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
1371{
1372 return -ENOSYS;
1373}
1374
1375static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
1376{
1377 struct j6_audio_device *adev = (struct j6_audio_device *)dev;
1378 struct j6_stream_out *out = adev->out;
1379 int ret = 0;
1380
1381 ALOGV("adev_set_mode() mode=0x%08x", mode);
1382
1383 pthread_mutex_lock(&adev->lock);
1384 pthread_mutex_lock(&out->lock);
1385
1386 if (adev->mode == mode) {
1387 ALOGV("adev_set_mode() already in mode=0x%08x", mode);
1388 goto out;
1389 }
1390
1391 if (mode == AUDIO_MODE_IN_CALL) {
1392 ret = enter_voice_call(adev);
1393 if (ret) {
1394 ALOGE("adev_set_mode() failed to initialize voice call %d", ret);
1395 goto out;
1396 }
1397 } else if (adev->mode == AUDIO_MODE_IN_CALL) {
1398 leave_voice_call(adev);
1399 }
1400
1401 adev->mode = mode;
1402
1403out:
1404 pthread_mutex_unlock(&out->lock);
1405 pthread_mutex_unlock(&adev->lock);
1406
1407 return ret;
1408}
1409
1410static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
1411{
1412 struct j6_audio_device *adev = (struct j6_audio_device *)dev;
1413
1414 ALOGV("adev_set_mic_mute() state=%s", state ? "mute" : "unmute");
1415 adev->mic_mute = state;
1416
1417 return 0;
1418}
1419
1420static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
1421{
1422 const struct j6_audio_device *adev = (const struct j6_audio_device *)dev;
1423
1424 *state = adev->mic_mute;
1425 ALOGV("adev_get_mic_mute() state=%s", *state ? "mute" : "unmute");
1426
1427 return 0;
1428}
1429
1430static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
1431 const struct audio_config *config)
1432{
1433 size_t bytes = get_input_buffer_size(config->sample_rate,
1434 config->format,
1435 popcount(config->channel_mask));
1436
1437 ALOGVV("adev_in_get_buffer_size() bytes=%u", bytes);
1438
1439 return bytes;
1440}
1441
1442static int adev_open_input_stream(struct audio_hw_device *dev,
1443 audio_io_handle_t handle,
1444 audio_devices_t devices,
1445 struct audio_config *config,
1446 struct audio_stream_in **stream_in,
1447 audio_input_flags_t flags __unused,
1448 const char *address __unused,
1449 audio_source_t source __unused)
1450{
1451 struct j6_audio_device *adev = (struct j6_audio_device *)dev;
1452 struct j6_stream_in *in;
1453 int ret;
1454
1455 in = (struct j6_stream_in *)malloc(sizeof(struct j6_stream_in));
1456 if (!in)
1457 return -ENOMEM;
1458
1459 ALOGV("adev_open_input_stream() stream=%p rate=%u channels=%u format=0x%08x",
1460 in, config->sample_rate, popcount(config->channel_mask), config->format);
1461
1462 pthread_mutex_init(&in->lock, NULL);
1463
1464 in->stream.common.get_sample_rate = in_get_sample_rate;
1465 in->stream.common.set_sample_rate = in_set_sample_rate;
1466 in->stream.common.get_buffer_size = in_get_buffer_size;
1467 in->stream.common.get_channels = in_get_channels;
1468 in->stream.common.get_format = in_get_format;
1469 in->stream.common.set_format = in_set_format;
1470 in->stream.common.standby = in_standby;
1471 in->stream.common.dump = in_dump;
1472 in->stream.common.set_parameters = in_set_parameters;
1473 in->stream.common.get_parameters = in_get_parameters;
1474 in->stream.common.add_audio_effect = in_add_audio_effect;
1475 in->stream.common.remove_audio_effect = in_remove_audio_effect;
1476 in->stream.set_gain = in_set_gain;
1477 in->stream.read = in_read;
1478 in->stream.get_input_frames_lost = in_get_input_frames_lost;
1479
1480 in->dev = adev;
1481 in->standby = true;
1482 in->config = pcm_config_capture;
1483 in->requested_rate = config->sample_rate;
1484 in->requested_channels = popcount(config->channel_mask);
1485 in->hw_frame_size = in->config.channels * sizeof(int16_t);
1486 in->remix = NULL;
1487 in->resampler = NULL;
1488 in->buffer = NULL;
1489 adev->in = in;
1490
1491 /* in-place stereo-to-mono remix since capture stream is stereo */
1492 if (in->requested_channels == 1) {
1493 ALOGV("adev_open_input_stream() stereo-to-mono remix needed");
1494
1495 /*
1496 * buffer size is already enough to allow stereo-to-mono remix
1497 * and resample if needed
1498 */
1499 in->buffer = malloc(2 * in->config.period_size * in->hw_frame_size);
1500 if (!in->buffer) {
1501 ret = -ENOMEM;
1502 goto err1;
1503 }
1504
1505 ret = setup_stereo_to_mono_input_remix(in);
1506 if (ret) {
1507 ALOGE("adev_open_input_stream() failed to setup remix %d", ret);
1508 goto err2;
1509 }
1510 }
1511
1512 if (in->requested_rate != in->config.rate) {
1513 ALOGV("adev_open_input_stream() resample needed, req=%uHz got=%uHz",
1514 in->requested_rate, in->config.rate);
1515
1516 in->buf_provider.get_next_buffer = get_next_buffer;
1517 in->buf_provider.release_buffer = release_buffer;
1518 ret = create_resampler(in->config.rate,
1519 in->requested_rate,
1520 in->requested_channels,
1521 RESAMPLER_QUALITY_DEFAULT,
1522 &in->buf_provider,
1523 &in->resampler);
1524 if (ret) {
1525 ALOGE("adev_open_input_stream() failed to create resampler %d", ret);
1526 goto err3;
1527 }
1528 }
1529
1530 *stream_in = &in->stream;
1531
1532 return 0;
1533
1534 err3:
1535 free(in->remix);
1536 err2:
1537 free(in->buffer);
1538 err1:
1539 free(in);
1540 return ret;
1541}
1542
1543static void adev_close_input_stream(struct audio_hw_device *dev,
1544 struct audio_stream_in *stream)
1545{
1546 struct j6_audio_device *adev = (struct j6_audio_device *)dev;
1547 struct j6_stream_in *in = (struct j6_stream_in *)(stream);
1548
1549 ALOGV("adev_close_input_stream() stream=%p", stream);
1550
1551 in_standby(&stream->common);
1552
1553 if (in->resampler)
1554 release_resampler(in->resampler);
1555 in->resampler = NULL;
1556
1557 if (in->remix)
1558 free(in->remix);
1559 in->remix = NULL;
1560
1561 in->dev = NULL;
1562 adev->in = NULL;
1563
1564 free(in->buffer);
1565 free(in);
1566}
1567
1568static int adev_dump(const audio_hw_device_t *device, int fd)
1569{
1570 return 0;
1571}
1572
1573/*
1574 * should not be needed for API version 2.0 but AudioFlinger uses it to find
1575 * suitable hw device, so we keep it
1576 */
1577static uint32_t adev_get_supported_devices(const struct audio_hw_device *dev)
1578{
1579 uint32_t devices = SUPPORTED_IN_DEVICES | SUPPORTED_OUT_DEVICES;
1580
1581 ALOGV("adev_get_supported_devices() devices=0x%08x", devices);
1582
1583 return devices;
1584}
1585
1586static int adev_close(hw_device_t *device)
1587{
1588 struct j6_audio_device *adev = (struct j6_audio_device *)device;
1589
1590 ALOGI("adev_close()");
1591
1592 audio_route_free(adev->route);
1593 free(device);
1594
1595 return 0;
1596}
1597
1598static int adev_open(const hw_module_t* module, const char* name,
1599 hw_device_t** device)
1600{
1601 struct j6_audio_device *adev;
1602
1603 ALOGI("adev_open() %s", name);
1604
1605 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
1606 return -EINVAL;
1607
1608 adev = (struct j6_audio_device*)malloc(sizeof(struct j6_audio_device));
1609 if (!adev)
1610 return -ENOMEM;
1611
1612 pthread_mutex_init(&adev->lock, NULL);
1613
1614 adev->device.common.tag = HARDWARE_DEVICE_TAG;
1615 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
1616 adev->device.common.module = (struct hw_module_t *) module;
1617 adev->device.common.close = adev_close;
1618
1619 adev->device.get_supported_devices = adev_get_supported_devices;
1620 adev->device.init_check = adev_init_check;
1621 adev->device.set_voice_volume = adev_set_voice_volume;
1622 adev->device.set_master_volume = adev_set_master_volume;
1623 adev->device.get_master_volume = adev_get_master_volume;
1624 adev->device.set_master_mute = adev_set_master_mute;
1625 adev->device.get_master_mute = adev_get_master_mute;
1626 adev->device.set_mode = adev_set_mode;
1627 adev->device.set_mic_mute = adev_set_mic_mute;
1628 adev->device.get_mic_mute = adev_get_mic_mute;
1629 adev->device.set_parameters = adev_set_parameters;
1630 adev->device.get_parameters = adev_get_parameters;
1631 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
1632 adev->device.open_output_stream = adev_open_output_stream;
1633 adev->device.close_output_stream = adev_close_output_stream;
1634 adev->device.open_input_stream = adev_open_input_stream;
1635 adev->device.close_input_stream = adev_close_input_stream;
1636 adev->device.dump = adev_dump;
1637
1638 adev->in_device = AUDIO_DEVICE_IN_BUILTIN_MIC;
1639 adev->out_device = AUDIO_DEVICE_OUT_SPEAKER;
1640 adev->card = find_supported_card();
1641 adev->in_port = 0;
1642 adev->out_port = 0;
1643 adev->bt_port = 2;
1644 adev->mic_mute = false;
1645 adev->in_call = false;
1646 adev->mode = AUDIO_MODE_NORMAL;
1647
1648 adev->route = audio_route_init(adev->card, NULL);
1649 if (!adev->route) {
1650 ALOGE("Unable to initialize audio routes");
1651 free(adev);
1652 return -EINVAL;
1653 }
1654
1655 *device = &adev->device.common;
1656
1657 return 0;
1658}
1659
1660static struct hw_module_methods_t hal_module_methods = {
1661 .open = adev_open,
1662};
1663
1664struct audio_module HAL_MODULE_INFO_SYM = {
1665 .common = {
1666 .tag = HARDWARE_MODULE_TAG,
1667 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
1668 .hal_api_version = HARDWARE_HAL_API_VERSION,
1669 .id = AUDIO_HARDWARE_MODULE_ID,
1670 .name = "Jacinto6 Audio HAL",
1671 .author = "Texas Instruments Inc.",
1672 .methods = &hal_module_methods,
1673 },
1674};
diff --git a/audio/legacy/audio_policy.conf b/audio/legacy/audio_policy.conf
new file mode 100644
index 0000000..a806163
--- /dev/null
+++ b/audio/legacy/audio_policy.conf
@@ -0,0 +1,94 @@
1# Global configuration section: lists input and output devices always present on the device
2# as well as the output device selected by default.
3# Devices are designated by a string that corresponds to the enum in audio.h
4
5global_configuration {
6 attached_output_devices AUDIO_DEVICE_OUT_SPEAKER
7 default_output_device AUDIO_DEVICE_OUT_SPEAKER
8 attached_input_devices AUDIO_DEVICE_IN_BUILTIN_MIC
9}
10
11# audio hardware module section: contains descriptors for all audio hw modules present on the
12# device. Each hw module node is named after the corresponding hw module library base name.
13# For instance, "primary" corresponds to audio.primary.<device>.so.
14# The "primary" module is mandatory and must include at least one output with
15# AUDIO_OUTPUT_FLAG_PRIMARY flag.
16# Each module descriptor contains one or more output profile descriptors and zero or more
17# input profile descriptors. Each profile lists all the parameters supported by a given output
18# or input stream category.
19# The "channel_masks", "formats", "devices" and "flags" are specified using strings corresponding
20# to enums in audio.h and audio_policy.h. They are concatenated by use of "|" without space or "\n".
21
22audio_hw_modules {
23 primary {
24 outputs {
25 primary {
26 sampling_rates 44100
27 channel_masks AUDIO_CHANNEL_OUT_STEREO
28 formats AUDIO_FORMAT_PCM_16_BIT
29 devices AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE
30 flags AUDIO_OUTPUT_FLAG_PRIMARY
31 }
32 }
33 inputs {
34 primary {
35 sampling_rates 8000|11025|16000|22050|32000|44100|48000
36 channel_masks AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO
37 formats AUDIO_FORMAT_PCM_16_BIT
38 devices AUDIO_DEVICE_IN_BUILTIN_MIC
39 }
40 }
41 }
42 hdmi {
43 outputs {
44 stereo {
45 sampling_rates 44100|48000
46 channel_masks AUDIO_CHANNEL_OUT_STEREO
47 formats AUDIO_FORMAT_PCM_16_BIT
48 devices AUDIO_DEVICE_OUT_AUX_DIGITAL
49 }
50 multichannel {
51 sampling_rates 44100|48000
52 channel_masks dynamic
53 formats AUDIO_FORMAT_PCM_16_BIT
54 devices AUDIO_DEVICE_OUT_AUX_DIGITAL
55 flags AUDIO_OUTPUT_FLAG_DIRECT
56 }
57 }
58 }
59 a2dp {
60 outputs {
61 a2dp {
62 sampling_rates 44100
63 channel_masks AUDIO_CHANNEL_OUT_STEREO
64 formats AUDIO_FORMAT_PCM_16_BIT
65 devices AUDIO_DEVICE_OUT_ALL_A2DP
66 }
67 }
68 }
69 r_submix {
70 outputs {
71 r_submix {
72 sampling_rates 44100|48000
73 channel_masks AUDIO_CHANNEL_OUT_STEREO
74 formats AUDIO_FORMAT_PCM_16_BIT
75 devices AUDIO_DEVICE_OUT_REMOTE_SUBMIX
76 }
77 multichannel {
78 sampling_rates 44100|48000
79 channel_masks AUDIO_CHANNEL_OUT_5POINT1
80 formats AUDIO_FORMAT_PCM_16_BIT
81 devices AUDIO_DEVICE_OUT_REMOTE_SUBMIX
82 flags AUDIO_OUTPUT_FLAG_DIRECT
83 }
84 }
85 inputs {
86 r_submix {
87 sampling_rates 44100|48000
88 channel_masks AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO|AUDIO_CHANNEL_IN_5POINT1EMUL
89 formats AUDIO_FORMAT_PCM_16_BIT
90 devices AUDIO_DEVICE_IN_REMOTE_SUBMIX
91 }
92 }
93 }
94}
diff --git a/audio/mixer_paths.xml b/audio/mixer_paths.xml
new file mode 100644
index 0000000..09949fa
--- /dev/null
+++ b/audio/mixer_paths.xml
@@ -0,0 +1,85 @@
1<mixer>
2
3<!-- Card default routes -->
4
5<!-- Capture: Mic -->
6<ctl name="Left PGA Mixer Mic3L Switch" value="1" />
7<ctl name="Right PGA Mixer Mic3R Switch" value="1" />
8<ctl name="PGA Capture Switch" value="1" />
9<ctl name="PGA Capture Volume" value="24" />
10<ctl name="Left Line1L Mux" value="single-ended" />
11<ctl name="Right Line1L Mux" value="single-ended" />
12<ctl name="Left Line1R Mux" value="single-ended" />
13<ctl name="Right Line1R Mux" value="single-ended" />
14
15<!-- Playback: Line-Out and Headphone -->
16<ctl name="Left DAC Mux" value="DAC_L1" />
17<ctl name="Right DAC Mux" value="DAC_R1" />
18<ctl name="PCM Playback Volume" value="127" />
19
20<ctl name="Left HP Mixer DACL1 Switch" value="1" />
21<ctl name="Right HP Mixer DACR1 Switch" value="1" />
22<ctl name="HP Playback Switch" value="1" />
23<ctl name="HP DAC Playback Volume" value="118" />
24<ctl name="Output Driver Power-On time" value="200ms" />
25
26<ctl name="Left Line Mixer DACL1 Switch" value="1" />
27<ctl name="Right Line Mixer DACR1 Switch" value="1" />
28<ctl name="Line Playback Switch" value="1" />
29<ctl name="Line DAC Playback Volume" value="118" />
30
31<!-- JAMR3 board, codec-A input: Line-In -->
32<ctl name="J3A Left PGA Mixer Line1L Switch" value="1" />
33<ctl name="J3A Right PGA Mixer Line1R Switch" value="1" />
34<ctl name="J3A PGA Capture Switch" value="1" />
35<ctl name="J3A PGA Capture Volume" value="0" />
36<ctl name="J3A Left Line1L Mux" value="differential" />
37<ctl name="J3A Right Line1L Mux" value="differential" />
38<ctl name="J3A Left Line1R Mux" value="differential" />
39<ctl name="J3A Right Line1R Mux" value="differential" />
40
41<!-- JAMR3 board, codec-B input: Mic -->
42<ctl name="J3B Left PGA Mixer Line1L Switch" value="1" />
43<ctl name="J3B Right PGA Mixer Line1R Switch" value="1" />
44<ctl name="J3B PGA Capture Switch" value="1" />
45<ctl name="J3B PGA Capture Volume" value="0" />
46<ctl name="J3B Left Line1L Mux" value="differential" />
47<ctl name="J3B Right Line1L Mux" value="differential" />
48<ctl name="J3B Left Line1R Mux" value="differential" />
49<ctl name="J3B Right Line1R Mux" value="differential" />
50
51<!-- JAMR3 board, codec-A output: Line-Out -->
52<ctl name="J3A Left DAC Mux" value="DAC_L1" />
53<ctl name="J3A Right DAC Mux" value="DAC_R1" />
54<ctl name="J3A Left Line Mixer DACL1 Switch" value="1" />
55<ctl name="J3A Right Line Mixer DACR1 Switch" value="1" />
56<ctl name="J3A Line DAC Playback Volume" value="118" />
57<ctl name="J3A Line Playback Switch" value="1" />
58<ctl name="J3A PCM Playback Volume" value="127" />
59
60<!-- JAMR3 board, codec-B Output: Line-Out -->
61<ctl name="J3B Left DAC Mux" value="DAC_L1" />
62<ctl name="J3B Right DAC Mux" value="DAC_R1" />
63<ctl name="J3B Left Line Mixer DACL1 Switch" value="1" />
64<ctl name="J3B Right Line Mixer DACR1 Switch" value="1" />
65<ctl name="J3B Line DAC Playback Volume" value="118" />
66<ctl name="J3B Line Playback Switch" value="1" />
67<ctl name="J3B PCM Playback Volume" value="127" />
68
69<!-- JAMR3 board, codec-C Output: Line-Out -->
70<ctl name="J3C Left DAC Mux" value="DAC_L1" />
71<ctl name="J3C Right DAC Mux" value="DAC_R1" />
72<ctl name="J3C Left Line Mixer DACL1 Switch" value="1" />
73<ctl name="J3C Right Line Mixer DACR1 Switch" value="1" />
74<ctl name="J3C Line DAC Playback Volume" value="118" />
75<ctl name="J3C Line Playback Switch" value="1" />
76<ctl name="J3C PCM Playback Volume" value="127" />
77
78<!-- Bluetooth -->
79<ctl name="Bluetooth Mode" value="Slave" />
80
81<path name="BT SCO Master">
82 <ctl name="Bluetooth Mode" value="Master" />
83</path>
84
85</mixer>
diff --git a/audio/multizone/Android.mk b/audio/multizone/Android.mk
new file mode 100644
index 0000000..bf1c4d7
--- /dev/null
+++ b/audio/multizone/Android.mk
@@ -0,0 +1,53 @@
1# Copyright (C) 2013 Texas Instruments
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15LOCAL_PATH := $(call my-dir)
16
17include $(CLEAR_VARS)
18LOCAL_MODULE := audio_policy.conf
19LOCAL_MODULE_TAGS := optional
20LOCAL_MODULE_CLASS := ETC
21LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
22LOCAL_SRC_FILES := $(LOCAL_MODULE)
23include $(BUILD_PREBUILT)
24
25include $(CLEAR_VARS)
26
27LOCAL_MODULE := audio.primary.$(TARGET_BOARD_PLATFORM)
28
29LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
30
31LOCAL_SRC_FILES := \
32 AudioHw.cpp \
33 audio_hw.cpp
34
35LOCAL_C_INCLUDES += \
36 system/media/audio_utils/include \
37 system/media/audio_effects/include \
38 device/ti/common-open/audio/utils/include
39
40LOCAL_SHARED_LIBRARIES := \
41 liblog \
42 libtiaudioutils \
43 libcutils \
44 libutils
45
46LOCAL_SHARED_LIBRARIES += libstlport
47include external/stlport/libstlport.mk
48
49LOCAL_STATIC_LIBRARIES := libmedia_helper
50
51LOCAL_MODULE_TAGS := optional
52
53include $(BUILD_SHARED_LIBRARY)
diff --git a/audio/multizone/AudioHw.cpp b/audio/multizone/AudioHw.cpp
new file mode 100644
index 0000000..38d06ed
--- /dev/null
+++ b/audio/multizone/AudioHw.cpp
@@ -0,0 +1,1276 @@
1/*
2 * Copyright (C) 2013 Texas Instruments
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "AudioHw"
18// #define LOG_NDEBUG 0
19// #define VERY_VERBOSE_LOGGING
20#ifdef VERY_VERBOSE_LOGGING
21#define ALOGVV ALOGV
22#else
23#define ALOGVV(...) do { } while(0)
24#endif
25
26#include <cutils/log.h>
27#include <cutils/properties.h>
28#include <media/AudioParameter.h>
29
30#include <AudioHw.h>
31
32namespace android {
33
34AudioStreamOut::AudioStreamOut(AudioHwDevice *hwDev,
35 PcmWriter *writer,
36 const PcmParams &params,
37 const SlotMap &map,
38 audio_devices_t devices)
39 : mHwDev(hwDev), mNullWriter(&mNullPort, params), mWriter(writer),
40 mParams(params), mDevices(devices), mStandby(true), mUsedForVoiceCall(false)
41{
42 if (mWriter)
43 mStream = new AdaptedOutStream(params, map);
44}
45
46int AudioStreamOut::initCheck() const
47{
48 int ret = 0;
49
50 if (!mHwDev) {
51 ALOGE("AudioStreamOut: initCheck() invalid AudioHwDevice");
52 ret = -ENODEV;
53 }
54 else if (!mWriter || !mWriter->initCheck()) {
55 ALOGE("AudioStreamOut: initCheck() invalid PCM writer");
56 ret = -ENODEV;
57 }
58 else if (mStream == NULL || !mStream->initCheck()) {
59 ALOGE("AudioStreamOut: initCheck() invalid Out Stream");
60 ret = -ENODEV;
61 }
62
63 ALOGV("AudioStreamOut: init check %d", ret);
64
65 return ret;
66}
67
68uint32_t AudioStreamOut::getSampleRate() const
69{
70 uint32_t rate = mParams.sampleRate;
71
72 ALOGVV("AudioStreamOut: getSampleRate() %u Hz", rate);
73
74 return rate;
75}
76
77int AudioStreamOut::setSampleRate(uint32_t rate)
78{
79 ALOGV("AudioStreamOut: setSampleRate() %u Hz", rate);
80
81 return 0;
82}
83
84size_t AudioStreamOut::getBufferSize() const
85{
86 size_t size;
87
88 /* Take resampling ratio into account and align to the nearest
89 * 16 frames as required by the AudioFlinger */
90 size = (mParams.frameCount * mParams.sampleRate) / mWriter->getParams().sampleRate;
91 size = ((size + 15) & ~15) * mParams.frameSize();
92
93 ALOGVV("AudioStreamOut: getBufferSize() %u bytes", size);
94
95 return size;
96}
97
98audio_channel_mask_t AudioStreamOut::getChannels() const
99{
100 uint32_t channels = mParams.channels;
101
102 ALOGVV("AudioStreamOut: getChannels() %u channels", channels);
103
104 return audio_channel_out_mask_from_count(channels);
105}
106
107audio_format_t AudioStreamOut::getFormat() const
108{
109 uint32_t sampleBits = mParams.sampleBits;
110
111 ALOGVV("AudioStreamOut: getFormat() %u bits/sample", sampleBits);
112
113 switch (sampleBits) {
114 case 8:
115 return AUDIO_FORMAT_PCM_8_BIT;
116 case 24:
117 return AUDIO_FORMAT_PCM_8_24_BIT;
118 case 32:
119 return AUDIO_FORMAT_PCM_32_BIT;
120 case 16:
121 default:
122 return AUDIO_FORMAT_PCM_16_BIT;
123 }
124}
125
126int AudioStreamOut::setFormat(audio_format_t format)
127{
128 ALOGV("AudioStreamOut: setFormat() %u bits/sample",
129 audio_bytes_per_sample(format) * 8);
130
131 return 0;
132}
133
134/* must be called with mLock */
135int AudioStreamOut::resume()
136{
137 ALOGV("AudioStreamOut: resume using %s writer",
138 mUsedForVoiceCall ? "null" : "regular");
139
140 /*
141 * Switching PCM writers is done under the assumption that the non-null
142 * writer (mWriter) is always open (but possibly in standby), which is
143 * achieved by using the primary output for voice calls.
144 */
145 PcmWriter *writer;
146 if (mUsedForVoiceCall)
147 writer = &mNullWriter;
148 else
149 writer = mWriter;
150
151 int ret = writer->registerStream(mStream);
152 if (ret) {
153 ALOGE("AudioStreamOut: failed to register stream %d", ret);
154 return ret;
155 }
156
157 ret = mStream->start();
158 if (ret) {
159 ALOGE("AudioStreamOut: failed to start stream %d", ret);
160 writer->unregisterStream(mStream);
161 }
162
163 return ret;
164}
165
166/* must be called with mLock */
167void AudioStreamOut::idle()
168{
169 ALOGV("AudioStreamOut: idle using %s writer",
170 mUsedForVoiceCall ? "null" : "regular");
171
172 PcmWriter *writer;
173 if (mUsedForVoiceCall)
174 writer = &mNullWriter;
175 else
176 writer = mWriter;
177
178 mStream->stop();
179 writer->unregisterStream(mStream);
180}
181
182int AudioStreamOut::standby()
183{
184 ALOGV("AudioStreamOut: standby()");
185
186 AutoMutex lock(mLock);
187
188 if (!mStandby) {
189 idle();
190 mStandby = true;
191 }
192
193 return 0;
194}
195
196void AudioStreamOut::setVoiceCall(bool on)
197{
198 ALOGV("AudioStreamOut: setVoiceCall() %s", on ? "enter" : "leave");
199
200 AutoMutex lock(mLock);
201
202 /*
203 * Voice call reuses one of the PCM writers that is otherwise used
204 * for media. Media has to be re-routed to a null writer (that only
205 * consumes the data but doesn't write it to the hardware) when the
206 * voice call starts and routed back to the actual writer when the
207 * voice call stops.
208 * Temporarily entering standby helps transitioning to the null writer
209 * the next time that data is written to the stream if the voice call
210 * occurs at mid-stream.
211 */
212 if (mUsedForVoiceCall != on) {
213 if (!mStandby) {
214 idle();
215 mStandby = true;
216 }
217 mUsedForVoiceCall = on;
218 }
219}
220
221int AudioStreamOut::dump(int fd) const
222{
223 ALOGV("AudioStreamOut: dump()");
224 return 0;
225}
226
227audio_devices_t AudioStreamOut::getDevice() const
228{
229 ALOGV("AudioStreamOut: getDevice()");
230 return mDevices;
231}
232
233int AudioStreamOut::setParameters(const char *kv_pairs)
234{
235 ALOGV("AudioStreamOut: setParameters() '%s'", kv_pairs ? kv_pairs : "");
236
237 int ret;
238
239 AudioParameter parms = AudioParameter(String8(kv_pairs));
240 String8 key = String8(AudioParameter::keyRouting);
241 int device;
242
243 if ((ret = parms.getInt(key, device)) == NO_ERROR) {
244 if ((mDevices & AUDIO_DEVICE_OUT_ALL) != (unsigned int)device) {
245 standby();
246 }
247 if (device & ~(mHwDev->getSupportedDevices())) {
248 ALOGW("AudioStreamOut: setParameters() device(s) not supported, "
249 "will use default devices");
250 }
251 else
252 mDevices = device;
253 }
254
255 return ret;
256}
257
258char *AudioStreamOut::getParameters(const char *keys) const
259{
260 ALOGV("AudioStreamOut::getParameters()");
261 return NULL;
262}
263
264int AudioStreamOut::addAudioEffect(effect_handle_t effect) const
265{
266 ALOGV("AudioStreamOut: addAudioEffects()");
267 return 0;
268}
269
270int AudioStreamOut::removeAudioEffect(effect_handle_t effect) const
271{
272 ALOGV("AudioStreamOut: removeAudioEffects()");
273 return 0;
274}
275
276uint32_t AudioStreamOut::getLatency() const
277{
278 uint32_t latency = (1000 * getBufferSize()) / mWriter->getParams().sampleRate;
279
280 ALOGVV("AudioStreamOut: getLatency() %u ms", latency);
281
282 return latency;
283}
284
285int AudioStreamOut::setVolume(float left, float right)
286{
287 ALOGV("AudioStreamOut: setVolume() left=%.4f right=%.4f", left, right);
288 return -ENOSYS;
289}
290
291ssize_t AudioStreamOut::write(const void* buffer, size_t bytes)
292{
293 uint32_t frames = mParams.bytesToFrames(bytes);
294 int ret = 0;
295 uint32_t usecs = (frames * 1000000) / mParams.sampleRate;
296
297 ALOGVV("AudioStreamOut: write %u frames (%u bytes) buffer %p",
298 frames, bytes, buffer);
299
300 AutoMutex lock(mLock);
301
302 if (mStandby) {
303 ret = resume();
304 if (ret) {
305 ALOGE("AudioStreamOut: failed to resume stream %d", ret);
306 usleep(usecs); /* limits the rate of error messages */
307 return ret;
308 }
309 mStandby = false;
310 }
311
312 ret = mStream->write(buffer, frames);
313 if (ret < 0) {
314 ALOGE("AudioStreamOut: failed to write data %d", ret);
315 usleep(usecs);
316 } else {
317 ALOGW_IF(ret != (int)frames,
318 "AudioStreamOut: wrote only %d out of %d requested frames",
319 ret, frames);
320 bytes = mParams.framesToBytes(ret);
321 }
322
323 return bytes;
324}
325
326int AudioStreamOut::getRenderPosition(uint32_t *dsp_frames) const
327{
328 ALOGV("AudioStreamOut: getRenderPosition()");
329
330 return -EINVAL;
331}
332
333int AudioStreamOut::getNextWriteTimestamp(int64_t *timestamp) const
334{
335 ALOGVV("AudioStreamOut: getNextWriteTimestamp()");
336
337 return -EINVAL;
338}
339
340/* ---------------------------------------------------------------------------------------- */
341
342AudioStreamIn::AudioStreamIn(AudioHwDevice *hwDev,
343 PcmReader *reader,
344 const PcmParams &params,
345 const SlotMap &map,
346 audio_devices_t devices)
347 : mHwDev(hwDev), mReader(reader), mParams(params), mDevices(devices),
348 mSource(AUDIO_SOURCE_DEFAULT), mStandby(true)
349{
350 if (mReader)
351 mStream = new AdaptedInStream(params, map);
352}
353
354int AudioStreamIn::initCheck() const
355{
356 int ret = 0;
357
358 if (!mHwDev) {
359 ALOGE("AudioStreamIn: initCheck() invalid AudioHwDevice");
360 ret = -ENODEV;
361 }
362 else if (!mReader || !mReader->initCheck()) {
363 ALOGE("AudioStreamIn: initCheck() invalid PCM reader");
364 ret = -ENODEV;
365 }
366 else if (mStream == NULL || !mStream->initCheck()) {
367 ALOGE("AudioStreamIn: initCheck() invalid In Stream");
368 ret = -ENODEV;
369 }
370
371 ALOGV("AudioStreamIn: init check %d", ret);
372
373 return ret;
374}
375
376uint32_t AudioStreamIn::getSampleRate() const
377{
378 ALOGV("AudioStreamIn: getSampleRate()");
379
380 uint32_t rate = mParams.sampleRate;
381
382 return rate;
383}
384
385int AudioStreamIn::setSampleRate(uint32_t rate)
386{
387 ALOGV("AudioStreamIn: setSampleRate() %u Hz", rate);
388
389 return 0;
390}
391
392size_t AudioStreamIn::getBufferSize() const
393{
394 size_t size;
395
396 /* Take resampling ratio into account */
397 size = (mParams.frameCount * mParams.sampleRate) / mReader->getParams().sampleRate;
398 size = size * mParams.frameSize();
399
400 ALOGVV("AudioStreamIn: getBufferSize() %u bytes", size);
401
402 return size;
403}
404
405audio_channel_mask_t AudioStreamIn::getChannels() const
406{
407 ALOGV("AudioStreamIn: getChannels()");
408
409 return audio_channel_in_mask_from_count(mParams.channels);
410}
411
412audio_format_t AudioStreamIn::getFormat() const
413{
414 ALOGV("AudioStreamIn: getFormat()");
415
416 return AUDIO_FORMAT_PCM_16_BIT;
417}
418
419int AudioStreamIn::setFormat(audio_format_t format)
420{
421 ALOGV("AudioStreamIn: setFormat()");
422
423 return 0;
424}
425
426/* must be called with mLock */
427int AudioStreamIn::resume()
428{
429 int ret = mReader->registerStream(mStream);
430 if (ret) {
431 ALOGE("AudioStreamIn: failed to register Dest %d", ret);
432 return ret;
433 }
434
435 ret = mStream->start();
436 if (ret) {
437 ALOGE("AudioStreamIn: failed to start stream %d", ret);
438 mReader->unregisterStream(mStream);
439 }
440
441 return ret;
442}
443
444/* must be called with mLock */
445void AudioStreamIn::idle()
446{
447 mStream->stop();
448 mReader->unregisterStream(mStream);
449}
450
451int AudioStreamIn::standby()
452{
453 ALOGV("AudioStreamIn: standby()");
454
455 AutoMutex lock(mLock);
456
457 if (!mStandby) {
458 idle();
459 mStandby = true;
460 }
461
462 return 0;
463}
464
465int AudioStreamIn::dump(int fd) const
466{
467 ALOGV("AudioStreamIn: dump()");
468
469 return 0;
470}
471
472audio_devices_t AudioStreamIn::getDevice() const
473{
474 ALOGV("AudioStreamIn: getDevice()");
475
476 return mDevices;
477}
478
479int AudioStreamIn::setParameters(const char *kv_pairs)
480{
481 ALOGV("AudioStreamIn: setParameters() '%s'", kv_pairs ? kv_pairs : "");
482
483 int ret;
484
485 AudioParameter parms = AudioParameter(String8(kv_pairs));
486 String8 source_key = String8(AudioParameter::keyInputSource);
487 String8 device_key = String8(AudioParameter::keyRouting);
488 int source, device;
489
490 if ((ret = parms.getInt(source_key, source)) == NO_ERROR) {
491 /* no audio source uses 0 */
492 if ((mSource != (unsigned int)source) &&
493 (source != 0) &&
494 (source < AUDIO_SOURCE_CNT)) {
495 ALOGV("AudioStreamIn: setParameters() source changed [%d]->[%d]",
496 mSource, source);
497 mSource = (audio_source_t)source;
498 /* Nothing to do for AUDIO_PARAMETER_STREAM_INPUT_SOURCE, so only
499 * record the source and continue */
500 }
501 }
502
503 if ((ret = parms.getInt(device_key, device)) == NO_ERROR) {
504 if ((mDevices & AUDIO_DEVICE_IN_ALL) != (unsigned int)device) {
505 standby();
506 }
507 if (device & ~(mHwDev->getSupportedDevices())) {
508 ALOGW("AudioStreamIn: setParameters() device(s) not supported, "
509 "will use default devices");
510 }
511 else {
512 mDevices = device;
513 ALOGV("AudioStreamIn: setParameters() device set to [0x%x]",
514 mDevices);
515 }
516 }
517
518 return 0;
519}
520
521char *AudioStreamIn::getParameters(const char *keys) const
522{
523 ALOGV("AudioStreamIn: getParameters()");
524
525 return NULL;
526}
527
528int AudioStreamIn::addAudioEffect(effect_handle_t effect) const
529{
530 ALOGV("AudioStreamIn: addAudioEffect()");
531
532 return 0;
533}
534
535int AudioStreamIn::removeAudioEffect(effect_handle_t effect) const
536{
537 ALOGV("AudioStreamIn: removeAudioEffect()");
538
539 return 0;
540}
541
542int AudioStreamIn::setGain(float gain)
543{
544 ALOGV("AudioStreamIn: setGain()");
545
546 return 0;
547}
548
549ssize_t AudioStreamIn::read(void* buffer, size_t bytes)
550{
551 uint32_t frames = mParams.bytesToFrames(bytes);
552 int ret = 0;
553 uint32_t usecs = (frames * 1000000) / mParams.sampleRate;
554
555 ALOGVV("AudioStreamIn: read %u frames (%u bytes) buffer %p",
556 frames, bytes, buffer);
557
558 AutoMutex lock(mLock);
559
560 if (mStandby) {
561 ret = resume();
562 if (ret) {
563 ALOGE("AudioStreamIn: failed to resume stream %d", ret);
564 usleep(usecs); /* limits the rate of error messages */
565 return ret;
566 }
567 mStandby = false;
568 }
569
570 ret = mStream->read(buffer, frames);
571 if (ret < 0) {
572 ALOGE("AudioStreamIn: failed to read data %d", ret);
573 usleep(usecs);
574 bytes = ret;
575 } else {
576 ALOGW_IF(ret != (int)frames,
577 "AudioStreamIn: read only %d out of %d requested frames",
578 ret, frames);
579 bytes = mParams.framesToBytes(ret);
580 if (mHwDev->mMicMute)
581 memset(buffer, 0, bytes);
582 }
583
584 return bytes;
585}
586
587uint32_t AudioStreamIn::getInputFramesLost()
588{
589 ALOGVV("AudioStreamIn: getInputFrameLost()");
590
591 return 0;
592}
593
594/* ---------------------------------------------------------------------------------------- */
595
596const char *AudioHwDevice::kCabinVolumeHP = "HP DAC Playback Volume";
597const char *AudioHwDevice::kCabinVolumeLine = "Line DAC Playback Volume";
598const char *AudioHwDevice::kBTMode = "Bluetooth Mode";
599
600AudioHwDevice::AudioHwDevice(uint32_t card)
601 : mCardId(card), mMixer(mCardId), mMicMute(false), mMode(AUDIO_MODE_NORMAL)
602{
603 /*
604 * "multizone_audio.use_jamr" property is used to indicate if JAMR3
605 * board is available in the system:
606 * - Present
607 * o Cabin : port 1, slots 0 & 1
608 * o Mic : port 1, slot 2
609 * o Back Mic: port 1, slot 3
610 * - Not present
611 * o Cabin : port 0, slots 0 & 1
612 * o Mic : port 0, slots 0 & 1
613 */
614 char value[PROPERTY_VALUE_MAX];
615 if ((property_get("persist.audio.use_jamr", value, NULL) == 0) ||
616 !strcmp(value, "1") || !strcasecmp(value, "true")) {
617 mMediaPortId = kJAMR3PortId;
618 } else {
619 mMediaPortId = kCPUPortId;
620 }
621
622 ALOGI("AudioHwDevice: create hw device for card hw:%u Jacinto6 EVM %s",
623 card, usesJAMR3() ? "+ JAMR3" : "");
624
625 /* Mixer for dra7evm and input/output ports for JAMR3 PCM device */
626 for (uint32_t i = 0; i < kNumPorts; i++) {
627 ALSAInPort *inPort = new ALSAInPort(mCardId, i);
628 mInPorts.push_back(inPort);
629
630 ALSAOutPort *outPort = new ALSAOutPort(mCardId, i);
631 mOutPorts.push_back(outPort);
632 }
633
634 /* PCM parameters for the port associated with on-board audio:
635 * 2 channels, 16-bits/sample, 44.1kHz, buffer of 882 frames (capture) */
636 PcmParams params0(kCPUNumChannels, kSampleSize, kSampleRate, kCaptureFrameCount);
637 PcmReader *reader = new PcmReader(mInPorts[kCPUPortId], params0);
638 mReaders.push_back(reader);
639 /* 2 channels, 16-bits/sample, 44.1kHz, buffer of 1024 frames (playback) */
640 params0.frameCount = kPlaybackFrameCount;
641 PcmWriter *writer = new PcmWriter(mOutPorts[kCPUPortId], params0);
642 mWriters.push_back(writer);
643
644 /* PCM parameters for the port associated with JAMR3 audio:
645 * 8 channels, 16-bits/sample, 44.1kHz, buffer of 882 frames (capture) */
646 PcmParams params1(kJAMR3NumChannels, kSampleSize, kSampleRate, kCaptureFrameCount);
647 reader = new PcmReader(mInPorts[kJAMR3PortId], params1);
648 mReaders.push_back(reader);
649 /* 8 channels, 16-bits/sample, 44.1kHz, buffer of 1024 frames (playback) */
650 params1.frameCount = kPlaybackFrameCount;
651 writer = new PcmWriter(mOutPorts[kJAMR3PortId], params1);
652 mWriters.push_back(writer);
653
654 /* Voice call */
655 PcmParams paramsBT(kBTNumChannels, kSampleSize, kBTSampleRate, kBTFrameCount);
656 writer = new PcmWriter(mOutPorts[kBTPortId], paramsBT);
657 mWriters.push_back(writer);
658 reader = new PcmReader(mInPorts[kBTPortId], paramsBT);
659 mReaders.push_back(reader);
660
661 /* BT is configured as stereo but only the left channel carries data */
662 SlotMap slots;
663 slots[0] = 0;
664 slots[1] = 0;
665
666 /* Microphone slots are different in JAMR3 and CPU board */
667 SlotMap micSlots;
668 if (usesJAMR3()) {
669 micSlots[0] = 2;
670 micSlots[1] = 2;
671 } else {
672 micSlots[0] = 0;
673 micSlots[1] = 0;
674 }
675
676 /* Voice call uplink */
677 mULPipe = new tiaudioutils::MonoPipe(paramsBT,
678 (kVoiceCallPipeMs * paramsBT.sampleRate) / 1000);
679 mULPipeWriter = new PipeWriter(mULPipe);
680 mULPipeReader = new PipeReader(mULPipe);
681 mVoiceULInStream = new InStream(paramsBT, micSlots, mULPipeWriter);
682 mVoiceULOutStream = new OutStream(paramsBT, slots, mULPipeReader);
683
684 /* Voice call downlink */
685 mDLPipe = new tiaudioutils::MonoPipe(paramsBT,
686 (kVoiceCallPipeMs * params0.sampleRate) / 1000);
687 mDLPipeWriter = new PipeWriter(mDLPipe);
688 mDLPipeReader = new PipeReader(mDLPipe);
689 mVoiceDLInStream = new InStream(paramsBT, slots, mDLPipeWriter);
690 mVoiceDLOutStream = new OutStream(paramsBT, slots, mDLPipeReader);
691
692 mMixer.initRoutes();
693}
694
695AudioHwDevice::~AudioHwDevice()
696{
697 ALOGI("AudioHwDevice: destroy hw device for card hw:%u", mCardId);
698
699 if (mDLPipeWriter)
700 delete mDLPipeWriter;
701
702 if (mDLPipeReader)
703 delete mDLPipeReader;
704
705 if (mDLPipe)
706 delete mDLPipe;
707
708 if (mULPipeWriter)
709 delete mULPipeWriter;
710
711 if (mULPipeReader)
712 delete mULPipeReader;
713
714 if (mULPipe)
715 delete mULPipe;
716
717 for (WriterVect::const_iterator i = mWriters.begin(); i != mWriters.end(); ++i) {
718 delete (*i);
719 }
720 for (ReaderVect::const_iterator i = mReaders.begin(); i != mReaders.end(); ++i) {
721 delete (*i);
722 }
723 for (OutPortVect::iterator i = mOutPorts.begin(); i != mOutPorts.end(); ++i) {
724 delete (*i);
725 }
726 for (InPortVect::iterator i = mInPorts.begin(); i != mInPorts.end(); ++i) {
727 delete (*i);
728 }
729}
730
731uint32_t AudioHwDevice::getSupportedDevices() const
732{
733 uint32_t devices;
734
735 devices = AUDIO_DEVICE_IN_BUILTIN_MIC |
736 AUDIO_DEVICE_IN_BACK_MIC |
737 AUDIO_DEVICE_IN_VOICE_CALL |
738 AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET |
739 AUDIO_DEVICE_OUT_SPEAKER |
740 AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
741 AUDIO_DEVICE_OUT_WIRED_HEADSET |
742 AUDIO_DEVICE_OUT_WIRED_HEADPHONE2;
743 ALOGV("AudioHwDevice: supported devices 0x%08x", devices);
744
745 return devices;
746}
747
748int AudioHwDevice::initCheck() const
749{
750 if (!mMixer.initCheck()) {
751 ALOGE("AudioHwDevice: ALSA mixer init failed");
752 return -ENODEV;
753 }
754
755 for (ReaderVect::const_iterator i = mReaders.begin(); i != mReaders.end(); ++i) {
756 if (!((*i)->initCheck())) {
757 ALOGE("AudioHwDevice: PCM reader initCheck failed");
758 return -ENODEV;
759 }
760 }
761 for (WriterVect::const_iterator i = mWriters.begin(); i != mWriters.end(); ++i) {
762 if (!((*i)->initCheck())) {
763 ALOGE("AudioHwDevice: PCM writer init failed");
764 return -ENODEV;
765 }
766 }
767
768 if ((mULPipe == NULL) || !mULPipe->initCheck() ||
769 (mULPipeReader == NULL) || !mULPipeReader->initCheck() ||
770 (mULPipeWriter == NULL) || !mULPipeWriter->initCheck()) {
771 ALOGE("AudioHwDevice: voice call uplink init check failed");
772 return -ENODEV;
773 }
774
775 if ((mDLPipe == NULL) || !mDLPipe->initCheck() ||
776 (mDLPipeReader == NULL) || !mDLPipeReader->initCheck() ||
777 (mDLPipeWriter == NULL) || !mDLPipeWriter->initCheck()) {
778 ALOGE("AudioHwDevice: voice call downlink init check failed");
779 return -ENODEV;
780 }
781
782 if ((mVoiceULInStream == NULL) || !mVoiceULInStream->initCheck() ||
783 (mVoiceULOutStream == NULL) || !mVoiceULOutStream->initCheck()) {
784 ALOGE("AudioHwDevice: voice call uplink streams init check failed");
785 return -ENODEV;
786 }
787
788 if ((mVoiceDLInStream == NULL) || !mVoiceDLInStream->initCheck() ||
789 (mVoiceDLOutStream == NULL) || !mVoiceDLOutStream->initCheck()) {
790 ALOGE("AudioHwDevice: voice call downlink streams init check failed");
791 return -ENODEV;
792 }
793
794 return 0;
795}
796
797int AudioHwDevice::setVoiceVolume(float volume)
798{
799 /* Linear interpolation between voice dB limits */
800 float dB = (kVoiceDBMax - kVoiceDBMin) * volume + kVoiceDBMin;
801
802 /* Output stage gain (-59.0dB, 0dB) with steps of 0.5dB */
803 int val = 2 * (dB + 59.0f);
804
805 ALOGV("AudioHwDevice: setVoiceVolume() vol=%.4f dB=%.4f", volume, dB, val);
806
807 mMixer.set(ALSAControl(kCabinVolumeHP, val), true);
808 mMixer.set(ALSAControl(kCabinVolumeLine, val), true);
809
810 return 0;
811}
812
813int AudioHwDevice::setMasterVolume(float volume)
814{
815 ALOGV("AudioHwDevice: setMasterVolume() vol=%.4f", volume);
816 return -ENOSYS;
817}
818
819const char *AudioHwDevice::getModeName(audio_mode_t mode) const
820{
821 switch (mode) {
822 case AUDIO_MODE_CURRENT:
823 return "CURRENT";
824 case AUDIO_MODE_NORMAL:
825 return "NORMAL";
826 case AUDIO_MODE_RINGTONE:
827 return "RINGTONE";
828 case AUDIO_MODE_IN_CALL:
829 return "IN_CALL";
830 case AUDIO_MODE_IN_COMMUNICATION:
831 return "COMMUNICATION";
832 default:
833 return "INVALID";
834 }
835}
836
837int AudioHwDevice::setMode(audio_mode_t mode)
838{
839 ALOGV("AudioHwDevice: setMode() %s", getModeName(mode));
840
841 AutoMutex lock(mLock);
842 if (mMode == mode) {
843 ALOGW("AudioHwDevice: already in mode %s", getModeName(mode));
844 return 0;
845 }
846
847 int ret = 0;
848 if (mode == AUDIO_MODE_IN_CALL) {
849 ret = enterVoiceCall();
850 ALOGE_IF(ret, "AudioHwDevice: failed to enter voice call %d", ret);
851 } else {
852 leaveVoiceCall();
853 }
854
855 if (!ret)
856 mMode = mode;
857
858 return ret;
859}
860
861int AudioHwDevice::enableVoiceCall()
862{
863 ALOGV("AudioHwDevice: enable voice call paths");
864
865 sp<AudioStreamOut> outStream = mPrimaryStreamOut.promote();
866 if (outStream == NULL) {
867 ALOGE("AudioHwDevice: primary output stream is not valid");
868 return -ENODEV;
869 }
870
871 /* Playback stream will free the writer and switch to a null writer */
872 outStream->setVoiceCall(true);
873
874 /* Uplink input stream: Mic -> Pipe */
875 int ret = mReaders[mMediaPortId]->registerStream(mVoiceULInStream);
876 if (ret) {
877 ALOGE("AudioHwDevice: failed to register uplink in stream %d", ret);
878 return ret;
879 }
880
881 /* Uplink output stream: Pipe -> Bluetooth */
882 ret = mWriters[kBTPortId]->registerStream(mVoiceULOutStream);
883 if (ret) {
884 ALOGE("AudioHwDevice: failed to register uplink out stream %d", ret);
885 return ret;
886 }
887
888 /* Downlink input stream: Bluetooth -> Pipe */
889 ret = mReaders[kBTPortId]->registerStream(mVoiceDLInStream);
890 if (ret) {
891 ALOGE("AudioHwDevice: failed to register downlink in stream %d", ret);
892 return ret;
893 }
894
895 /* Downlink output stream: Pipe -> Speaker */
896 ret = outStream->mWriter->registerStream(mVoiceDLOutStream);
897 if (ret) {
898 ALOGE("AudioHwDevice: failed to register downlink out stream %d", ret);
899 }
900
901 return ret;
902}
903
904void AudioHwDevice::disableVoiceCall()
905{
906 ALOGV("AudioHwDevice: disable voice call paths");
907
908 sp<AudioStreamOut> outStream = mPrimaryStreamOut.promote();
909 if (outStream != NULL) {
910 if (outStream->mWriter->isStreamRegistered(mVoiceDLOutStream))
911 outStream->mWriter->unregisterStream(mVoiceDLOutStream);
912 outStream->setVoiceCall(false);
913 } else {
914 ALOGE("AudioHwDevice: primary output stream is not valid");
915 }
916
917 if (mReaders[kBTPortId]->isStreamRegistered(mVoiceDLInStream))
918 mReaders[kBTPortId]->unregisterStream(mVoiceDLInStream);
919
920 if (mWriters[kBTPortId]->isStreamRegistered(mVoiceULOutStream))
921 mWriters[kBTPortId]->unregisterStream(mVoiceULOutStream);
922
923 if (mReaders[mMediaPortId]->isStreamRegistered(mVoiceULInStream))
924 mReaders[mMediaPortId]->unregisterStream(mVoiceULInStream);
925}
926
927int AudioHwDevice::enterVoiceCall()
928{
929 ALOGI("AudioHwDevice: enter voice call");
930
931 /* Setup uplink and downlink pipes */
932 int ret = enableVoiceCall();
933 if (ret) {
934 ALOGE("AudioHwDevice: failed to enable voice call path %d", ret);
935 return ret;
936 }
937
938 /* Bluetooth is master, provides BCLK and FSYNC */
939 mMixer.set(ALSAControl(kBTMode, "Master"), true);
940
941 mULPipe->shutdown(false);
942 mDLPipe->shutdown(false);
943
944 /* Uplink input stream: Mic -> Pipe */
945 ret = mVoiceULInStream->start();
946 if (ret) {
947 ALOGE("AudioHwDevice: failed to start uplink in stream %d", ret);
948 return ret;
949 }
950
951 /* Downlink input stream: Bluetooth -> Pipe */
952 ret = mVoiceDLInStream->start();
953 if (ret) {
954 ALOGE("AudioHwDevice: failed to start downlink in stream %d", ret);
955 return ret;
956 }
957
958 /*
959 * Wait till pipe is half full to give a head start to the output streams.
960 * The time to wait consists of the actual pipe size, the ADC settle time
961 * used in the kernel and the time needed to produce a BT audio buffer.
962 * Only the pipe size related time contributes to the steady state latency.
963 */
964 usleep((kVoiceCallPipeMs * 5000) + (kADCSettleMs * 1000) +
965 (kBTFrameCount * 1000) / kBTSampleRate);
966
967 /* Downlink output stream: Pipe -> Speaker */
968 ret = mVoiceDLOutStream->start();
969 if (ret) {
970 ALOGE("AudioHwDevice: failed to start downlink out stream %d", ret);
971 }
972
973 /* Uplink output stream: Pipe -> Bluetooth */
974 ret = mVoiceULOutStream->start();
975 if (ret) {
976 ALOGE("AudioHwDevice: failed to start uplink out stream %d", ret);
977 return ret;
978 }
979
980 return ret;
981}
982
983void AudioHwDevice::leaveVoiceCall()
984{
985 ALOGI("AudioHwDevice: leave voice call");
986
987 /*
988 * The PCM ports used for Bluetooth are slaves and they can lose the
989 * BCLK and FSYNC while still active. That leads to blocking read() and
990 * write() calls, which is prevented by switching the clock source to
991 * an internal one and explicitly stopping both ports for the new source
992 * to take effect at kernel level
993 */
994 mMixer.set(ALSAControl(kBTMode, "Slave"), true);
995
996 mULPipe->shutdown(true);
997 mDLPipe->shutdown(true);
998
999 /* Uplink input stream: Mic -> Pipe */
1000 if (mVoiceULInStream->isStarted())
1001 mVoiceULInStream->stop();
1002
1003 /* Downlink input stream: Bluetooth -> Pipe */
1004 mInPorts[kBTPortId]->stop();
1005 if (mVoiceDLInStream->isStarted())
1006 mVoiceDLInStream->stop();
1007
1008 /* Downlink output stream: Pipe -> Speaker */
1009 if (mVoiceDLOutStream->isStarted())
1010 mVoiceDLOutStream->stop();
1011
1012 /* Uplink output stream: Pipe -> Bluetooth */
1013 mOutPorts[kBTPortId]->stop();
1014 if (mVoiceULOutStream->isStarted())
1015 mVoiceULOutStream->stop();
1016
1017 mULPipe->flush();
1018 mDLPipe->flush();
1019
1020 disableVoiceCall();
1021
1022 /* Reset the cabin volume for media */
1023 setVoiceVolume(1.0f);
1024}
1025
1026int AudioHwDevice::setMicMute(bool state)
1027{
1028 ALOGV("AudioHwDevice: setMicMute() %s", state ? "mute" : "unmute");
1029
1030 mMicMute = state;
1031
1032 return 0;
1033}
1034
1035int AudioHwDevice::getMicMute(bool *state) const
1036{
1037 ALOGV("AudioHwDevice: getMicMute()");
1038
1039 *state = mMicMute;
1040
1041 return 0;
1042}
1043
1044int AudioHwDevice::setParameters(const char *kv_pairs)
1045{
1046 ALOGV("AudioHwDevice: setParameters() '%s'", kv_pairs ? kv_pairs : "");
1047
1048 return 0;
1049}
1050
1051char *AudioHwDevice::getParameters(const char *keys) const
1052{
1053 ALOGV("AudioHwDevice: getParameters()");
1054
1055 return NULL;
1056}
1057
1058size_t AudioHwDevice::getInputBufferSize(const struct audio_config *config) const
1059{
1060 ALOGV("AudioHwDevice: getInputBufferSize()");
1061
1062 AutoMutex lock(mLock);
1063 size_t size;
1064
1065 /* Take resampling ratio into account */
1066 /* Use port 0 for the calculation, since values for both ports are the same */
1067 uint32_t frames = mReaders[kCPUPortId]->getParams().frameCount;
1068 uint32_t rate = mReaders[kCPUPortId]->getParams().sampleRate;
1069
1070 size = (frames * config->sample_rate) / rate;
1071 size = size * mReaders[kCPUPortId]->getParams().frameSize();
1072
1073 ALOGV("AudioHwDevice: getInputBufferSize() %d bytes", size);
1074
1075 return size;
1076}
1077
1078int AudioHwDevice::dump(int fd) const
1079{
1080 ALOGV("AudioHwDevice: dump()");
1081
1082 return 0;
1083}
1084
1085int AudioHwDevice::setMasterMute(bool mute)
1086{
1087 ALOGV("AudioHwDevice: setMasterMute() %s", mute ? "mute" : "unmute");
1088 return -ENOSYS;
1089}
1090
1091AudioStreamIn* AudioHwDevice::openInputStream(audio_io_handle_t handle,
1092 audio_devices_t devices,
1093 struct audio_config *config)
1094{
1095 uint32_t port = mMediaPortId;
1096 uint32_t srcSlot0, srcSlot1;
1097 uint32_t channels = popcount(config->channel_mask);
1098
1099 ALOGV("AudioHwDevice: openInputStream()");
1100
1101 switch (devices) {
1102 case AUDIO_DEVICE_IN_BUILTIN_MIC:
1103 case AUDIO_DEVICE_IN_VOICE_CALL:
1104 if (usesJAMR3()) {
1105 srcSlot0 = 2;
1106 srcSlot1 = 2;
1107 } else {
1108 srcSlot0 = 0;
1109 srcSlot1 = 1;
1110 }
1111 break;
1112 case AUDIO_DEVICE_IN_BACK_MIC:
1113 if (usesJAMR3()) {
1114 srcSlot0 = 3;
1115 srcSlot1 = 3;
1116 } else {
1117 srcSlot0 = 0;
1118 srcSlot1 = 1;
1119 }
1120 break;
1121 case AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET:
1122 if (!usesJAMR3()) {
1123 ALOGE("AudioHwDevice: device 0x%08x requires JAMR3", devices);
1124 return NULL;
1125 }
1126 srcSlot0 = 0;
1127 srcSlot1 = 1;
1128 break;
1129 default:
1130 ALOGE("AudioHwDevice: device 0x%08x is not supported", devices);
1131 return NULL;
1132 }
1133
1134 SlotMap slotMap;
1135 if (channels >= 1)
1136 slotMap[0] = srcSlot0;
1137 if (channels == 2)
1138 slotMap[1] = srcSlot1;
1139 if (channels > 2) {
1140 ALOGE("AudioHwDevice: %u channels are not supported", channels);
1141 return NULL;
1142 }
1143
1144 if (!slotMap.isValid()) {
1145 ALOGE("AudioHwDevice: failed to create slot map");
1146 return NULL;
1147 }
1148
1149 AutoMutex lock(mLock);
1150
1151 /* Set the parameters for the internal input stream. Don't change the
1152 * parameters for capture. The resampler is used if needed. */
1153 PcmParams params(*config, mReaders[port]->getParams().frameCount);
1154
1155 sp<AudioStreamIn> in = new AudioStreamIn(this, mReaders[port], params,
1156 slotMap, devices);
1157 if ((in == NULL) || in->initCheck()) {
1158 ALOGE("AudioHwDevice: failed to open input stream on port hw:%u,%u",
1159 mCardId, port);
1160 return NULL;
1161 }
1162
1163 mInStreams.insert(in);
1164
1165 return in.get();
1166}
1167
1168void AudioHwDevice::closeInputStream(AudioStreamIn *in)
1169{
1170 ALOGV("AudioHwDevice: closeInputStream()");
1171
1172 AutoMutex lock(mLock);
1173
1174 if (mInStreams.find(in) == mInStreams.end()) {
1175 ALOGW("AudioHwDevice: input stream %p is not open", in);
1176 return;
1177 }
1178
1179 mInStreams.erase(in);
1180
1181 in = NULL;
1182}
1183
1184AudioStreamOut* AudioHwDevice::openOutputStream(audio_io_handle_t handle,
1185 audio_devices_t devices,
1186 audio_output_flags_t flags,
1187 struct audio_config *config)
1188{
1189 uint32_t port = 0;
1190 PcmParams params;
1191
1192 ALOGV("AudioHwDevice: openOutputStream()");
1193
1194 uint32_t destMask;
1195 switch (devices) {
1196 case AUDIO_DEVICE_OUT_SPEAKER:
1197 port = mMediaPortId;
1198 destMask = 0x03;
1199 break;
1200 case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
1201 case AUDIO_DEVICE_OUT_WIRED_HEADSET:
1202 port = kJAMR3PortId;
1203 destMask = 0x0c;
1204 break;
1205 case AUDIO_DEVICE_OUT_WIRED_HEADPHONE2:
1206 port = kJAMR3PortId;
1207 destMask = 0x30;
1208 break;
1209 default:
1210 ALOGE("AudioHwDevice: device 0x%08x is not supported", devices);
1211 return NULL;
1212 }
1213
1214 SlotMap slotMap(0x03, destMask);
1215 if (!slotMap.isValid()) {
1216 ALOGE("AudioHwDevice: failed to create slot map");
1217 return NULL;
1218 }
1219
1220 AutoMutex lock(mLock);
1221
1222 /* Set the parameters for the internal output stream */
1223 params.frameCount = mWriters[port]->getParams().frameCount;
1224 params.sampleRate = config->sample_rate; /* Use stream's resampler if needed */
1225 params.sampleBits = 16; /* 16-bits/sample */
1226 params.channels = 2; /* Listening zones are stereo */
1227
1228 /* Update audio config with granted parameters */
1229 if (popcount(config->channel_mask) != (int)params.channels) {
1230 ALOGV("AudioHwDevice: updating audio config channel mask [0x%x]->[0x%x]",
1231 config->channel_mask,
1232 audio_channel_out_mask_from_count(params.channels));
1233 }
1234 config->channel_mask = audio_channel_out_mask_from_count(params.channels);
1235 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
1236 ALOGV("AudioHwDevice: updating audio config format [0x%x]->[0x%x]",
1237 config->format, AUDIO_FORMAT_PCM_16_BIT);
1238 }
1239 config->format = AUDIO_FORMAT_PCM_16_BIT;
1240
1241 sp<AudioStreamOut> out = new AudioStreamOut(this, mWriters[port], params,
1242 slotMap, devices);
1243 if ((out == NULL) || out->initCheck()) {
1244 ALOGE("AudioHwDevice: failed to open output stream on port hw:%u,%u",
1245 mCardId, port);
1246 return NULL;
1247 }
1248
1249 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY)
1250 mPrimaryStreamOut = out;
1251
1252 mOutStreams.insert(out);
1253
1254 return out.get();
1255}
1256
1257void AudioHwDevice::closeOutputStream(AudioStreamOut *out)
1258{
1259 ALOGV("AudioHwDevice: closeOutputStream()");
1260
1261 AutoMutex lock(mLock);
1262
1263 if (mOutStreams.find(out) == mOutStreams.end()) {
1264 ALOGW("AudioHwDevice: output stream %p is not open", out);
1265 return;
1266 }
1267
1268 if (mPrimaryStreamOut == out)
1269 mPrimaryStreamOut = NULL;
1270
1271 mOutStreams.erase(out);
1272
1273 out = NULL;
1274}
1275
1276}; /* namespace android */
diff --git a/audio/multizone/AudioHw.h b/audio/multizone/AudioHw.h
new file mode 100644
index 0000000..0d475da
--- /dev/null
+++ b/audio/multizone/AudioHw.h
@@ -0,0 +1,251 @@
1/*
2 * Copyright (C) 2013 Texas Instruments
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _AUDIO_HW_H_
18#define _AUDIO_HW_H_
19
20#include <vector>
21
22#include <system/audio.h>
23#include <hardware/audio_effect.h>
24
25#include <tiaudioutils/Pcm.h>
26#include <tiaudioutils/NullPcm.h>
27#include <tiaudioutils/ALSAPcm.h>
28#include <tiaudioutils/ALSAMixer.h>
29#include <tiaudioutils/MumStream.h>
30#include <tiaudioutils/Stream.h>
31#include <tiaudioutils/Base.h>
32
33namespace android {
34
35using namespace tiaudioutils;
36using std::vector;
37
38class AudioHwDevice;
39
40class AudioStream {
41 public:
42 virtual ~AudioStream() {}
43 virtual uint32_t getSampleRate() const = 0;
44 virtual int setSampleRate(uint32_t rate) = 0;
45 virtual size_t getBufferSize() const = 0;
46 virtual audio_channel_mask_t getChannels() const = 0;
47 virtual audio_format_t getFormat() const = 0;
48 virtual int setFormat(audio_format_t format) = 0;
49 virtual int standby() = 0;
50 virtual int dump(int fd) const = 0;
51 virtual audio_devices_t getDevice() const = 0;
52 virtual int setDevice(audio_devices_t device) { return 0; } /* unused */
53 virtual int setParameters(const char *kv_pairs) = 0;
54 virtual char *getParameters(const char *keys) const = 0;
55 virtual int addAudioEffect(effect_handle_t effect) const = 0;
56 virtual int removeAudioEffect(effect_handle_t effect) const = 0;
57};
58
59class AudioStreamOut : public RefBase, public AudioStream {
60 public:
61 AudioStreamOut(AudioHwDevice *hwDev,
62 PcmWriter *writer,
63 const PcmParams &params,
64 const SlotMap &map,
65 audio_devices_t devices);
66 virtual ~AudioStreamOut() {};
67 int initCheck() const;
68
69 /* From AudioStream */
70 virtual uint32_t getSampleRate() const;
71 virtual int setSampleRate(uint32_t rate);
72 virtual size_t getBufferSize() const;
73 virtual audio_channel_mask_t getChannels() const;
74 virtual audio_format_t getFormat() const;
75 virtual int setFormat(audio_format_t format);
76 virtual int standby();
77 virtual int dump(int fd) const;
78 virtual audio_devices_t getDevice() const;
79 virtual int setParameters(const char *kv_pairs);
80 virtual char *getParameters(const char *keys) const;
81 virtual int addAudioEffect(effect_handle_t effect) const;
82 virtual int removeAudioEffect(effect_handle_t effect) const;
83
84 /* AudioStreamOut specific */
85 uint32_t getLatency() const;
86 int setVolume(float left, float right);
87 ssize_t write(const void* buffer, size_t bytes);
88 int getRenderPosition(uint32_t *dsp_frames) const;
89 int getNextWriteTimestamp(int64_t *timestamp) const;
90
91 void setVoiceCall(bool on);
92
93 friend AudioHwDevice;
94
95 protected:
96 int resume();
97 void idle();
98
99 AudioHwDevice *mHwDev;
100 NullOutPort mNullPort;
101 PcmWriter mNullWriter;
102 PcmWriter *mWriter;
103 PcmParams mParams;
104 audio_devices_t mDevices;
105 sp<OutStream> mStream;
106 bool mStandby;
107 bool mUsedForVoiceCall;
108 Mutex mLock;
109};
110
111class AudioStreamIn : public RefBase, public AudioStream {
112 public:
113 AudioStreamIn(AudioHwDevice *hwDev,
114 PcmReader *reader,
115 const PcmParams &params,
116 const SlotMap &map,
117 audio_devices_t devices);
118 virtual ~AudioStreamIn() {};
119 int initCheck() const;
120
121 /* From AudioStream */
122 virtual uint32_t getSampleRate() const;
123 virtual int setSampleRate(uint32_t rate);
124 virtual size_t getBufferSize() const;
125 virtual audio_channel_mask_t getChannels() const;
126 virtual audio_format_t getFormat() const;
127 virtual int setFormat(audio_format_t format);
128 virtual int standby();
129 virtual int dump(int fd) const;
130 virtual audio_devices_t getDevice() const;
131 virtual int setParameters(const char *kv_pairs);
132 virtual char *getParameters(const char *keys) const;
133 virtual int addAudioEffect(effect_handle_t effect) const;
134 virtual int removeAudioEffect(effect_handle_t effect) const;
135
136 /* AudioStreamIn specific */
137 int setGain(float gain);
138 ssize_t read(void* buffer, size_t bytes);
139 uint32_t getInputFramesLost();
140
141 protected:
142 int resume();
143 void idle();
144
145 AudioHwDevice *mHwDev;
146 PcmReader *mReader;
147 PcmParams mParams;
148 audio_devices_t mDevices;
149 audio_source_t mSource;
150 sp<InStream> mStream;
151 bool mStandby;
152 Mutex mLock;
153};
154
155class AudioHwDevice {
156 public:
157 AudioHwDevice(uint32_t card);
158 virtual ~AudioHwDevice();
159
160 uint32_t getSupportedDevices() const;
161 int initCheck() const;
162 int setVoiceVolume(float volume);
163 int setMasterVolume(float volume);
164 int setMode(audio_mode_t mode);
165 int setMicMute(bool state);
166 int getMicMute(bool *state) const;
167 int setParameters(const char *kv_pairs);
168 char *getParameters(const char *keys) const;
169 size_t getInputBufferSize(const struct audio_config *config) const;
170 int dump(int fd) const;
171 int setMasterMute(bool mute);
172 AudioStreamIn* openInputStream(audio_io_handle_t handle,
173 audio_devices_t devices,
174 struct audio_config *config);
175 void closeInputStream(AudioStreamIn *in);
176 AudioStreamOut* openOutputStream(audio_io_handle_t handle,
177 audio_devices_t devices,
178 audio_output_flags_t flags,
179 struct audio_config *config);
180 void closeOutputStream(AudioStreamOut *out);
181
182 friend class AudioStreamIn;
183 friend class AudioStreamOut;
184
185 static const uint32_t kNumPorts = 3;
186 static const uint32_t kCPUPortId = 0;
187 static const uint32_t kJAMR3PortId = 1;
188 static const uint32_t kBTPortId = 2;
189 static const uint32_t kCPUNumChannels = 2;
190 static const uint32_t kJAMR3NumChannels = 8;
191 static const uint32_t kBTNumChannels = 2;
192
193 static const uint32_t kSampleRate = 44100;
194 static const uint32_t kBTSampleRate = 8000;
195 static const uint32_t kSampleSize = 16;
196 static const uint32_t kCaptureFrameCount = 882;
197 static const uint32_t kPlaybackFrameCount = 1024;
198 static const uint32_t kBTFrameCount = 160;
199
200 static const uint32_t kADCSettleMs = 80;
201 static const uint32_t kVoiceCallPipeMs = 100;
202
203 static const float kVoiceDBMax = 0.0f;
204 static const float kVoiceDBMin = -24.0f;
205 static const char *kCabinVolumeHP;
206 static const char *kCabinVolumeLine;
207 static const char *kBTMode;
208
209 protected:
210 typedef set< sp<AudioStreamIn> > StreamInSet;
211 typedef set< sp<AudioStreamOut> > StreamOutSet;
212 typedef vector<ALSAInPort*> InPortVect;
213 typedef vector<ALSAOutPort*> OutPortVect;
214 typedef vector<PcmReader*> ReaderVect;
215 typedef vector<PcmWriter*> WriterVect;
216
217 bool usesJAMR3() const { return mMediaPortId == kJAMR3PortId; }
218 const char *getModeName(audio_mode_t mode) const;
219 int enterVoiceCall();
220 void leaveVoiceCall();
221 int enableVoiceCall();
222 void disableVoiceCall();
223
224 uint32_t mCardId;
225 ALSAMixer mMixer;
226 InPortVect mInPorts;
227 OutPortVect mOutPorts;
228 ReaderVect mReaders;
229 WriterVect mWriters;
230 StreamInSet mInStreams;
231 StreamOutSet mOutStreams;
232 bool mMicMute;
233 audio_mode_t mMode;
234 uint32_t mMediaPortId;
235 wp<AudioStreamOut> mPrimaryStreamOut;
236 tiaudioutils::MonoPipe *mULPipe;
237 tiaudioutils::MonoPipe *mDLPipe;
238 PipeWriter *mULPipeWriter;
239 PipeWriter *mDLPipeWriter;
240 PipeReader *mULPipeReader;
241 PipeReader *mDLPipeReader;
242 sp<InStream> mVoiceULInStream;
243 sp<InStream> mVoiceDLInStream;
244 sp<OutStream> mVoiceULOutStream;
245 sp<OutStream> mVoiceDLOutStream;
246 mutable Mutex mLock;
247};
248
249}; // namespace android
250
251#endif /* _AUDIO_HW_H_ */
diff --git a/audio/multizone/audio_hw.cpp b/audio/multizone/audio_hw.cpp
new file mode 100644
index 0000000..3e429c4
--- /dev/null
+++ b/audio/multizone/audio_hw.cpp
@@ -0,0 +1,562 @@
1/*
2 * Copyright (C) 2013 Texas Instruments
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "audio_hw_primary"
18/* #define LOG_NDEBUG 0 */
19
20#include <errno.h>
21#include <stdint.h>
22#include <stdlib.h>
23#include <sys/time.h>
24
25#include <cutils/log.h>
26#include <cutils/str_parms.h>
27#include <cutils/properties.h>
28
29#include <system/audio.h>
30#include <hardware/hardware.h>
31#include <hardware/audio.h>
32#include <hardware/audio_effect.h>
33
34#include <AudioHw.h>
35
36extern "C" {
37
38namespace android {
39
40struct mz_audio_device {
41 struct audio_hw_device device;
42 AudioHwDevice *hwDev;
43};
44
45struct mz_stream_in {
46 struct audio_stream_in stream;
47 AudioStreamIn *streamIn;
48};
49
50struct mz_stream_out {
51 struct audio_stream_out stream;
52 AudioStreamOut *streamOut;
53};
54
55static inline AudioHwDevice *toAudioHwDev(struct audio_hw_device *dev)
56{
57 return reinterpret_cast<struct mz_audio_device *>(dev)->hwDev;
58}
59
60static inline const AudioHwDevice *tocAudioHwDev(const struct audio_hw_device *dev)
61{
62 return reinterpret_cast<const struct mz_audio_device *>(dev)->hwDev;
63}
64
65static inline AudioStreamIn *toStreamIn(struct audio_stream_in *in)
66{
67 return reinterpret_cast<struct mz_stream_in *>(in)->streamIn;
68}
69
70static inline const AudioStreamIn *tocStreamIn(const struct audio_stream_in *in)
71{
72 return reinterpret_cast<const struct mz_stream_in *>(in)->streamIn;
73}
74
75static inline AudioStreamOut *toStreamOut(struct audio_stream_out *out)