summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYogesh Siraswar2018-01-17 15:29:58 -0600
committerYogesh Siraswar2018-01-17 15:29:58 -0600
commit6502befe40ac5922193dde753c8fcc62cd2ae9ad (patch)
tree21c14ab66e7a784fc1f6ef2e29c3af9c32d5e65f
downloaddevice-ti-am43xevm-6502befe40ac5922193dde753c8fcc62cd2ae9ad.tar.gz
device-ti-am43xevm-6502befe40ac5922193dde753c8fcc62cd2ae9ad.tar.xz
device-ti-am43xevm-6502befe40ac5922193dde753c8fcc62cd2ae9ad.zip
am43xevm device filed-marshmallow-mr3-release
These file were verified on AM438x EVM: 1) Android 6AM1.3 release 2) 4.4 kernel Signed-off-by: Yogesh Siraswar <yogeshs@ti.com>
-rw-r--r--Android.mk36
-rw-r--r--AndroidProducts.mk17
-rw-r--r--BoardConfig.mk86
-rw-r--r--CleanSpec.mk51
-rw-r--r--audio/Android.mk22
-rw-r--r--audio/audio_policy.conf102
-rw-r--r--audio/hdmi/Android.mk40
-rw-r--r--audio/hdmi/hdmi_audio_hal.h37
-rw-r--r--audio/hdmi/hdmi_audio_hw.c824
-rw-r--r--audio/hdmi/hdmi_audio_utils.c414
-rw-r--r--audio/primary/Android.mk43
-rw-r--r--audio/primary/audio_hw.c1770
-rw-r--r--audio/primary/mixer_paths.xml31
-rw-r--r--bluetooth/bdroid_buildcfg.h28
-rw-r--r--bootanimation.zipbin0 -> 8977591 bytes
-rw-r--r--device.mk154
-rw-r--r--egl.cfg2
-rwxr-xr-xfastboot.sh253
-rw-r--r--fstab.am43xevmboard13
-rw-r--r--full_am43xevm.mk32
-rwxr-xr-xinit.am43xevmboard.cpuset.sh5
-rw-r--r--init.am43xevmboard.rc134
-rw-r--r--init.am43xevmboard.usb.rc56
-rw-r--r--kernelbin0 -> 7678520 bytes
-rw-r--r--media_codecs.xml74
-rw-r--r--media_codecs_performance.xml97
-rw-r--r--media_profiles.xml664
-rw-r--r--overlay/frameworks/base/core/res/res/drawable-sw720dp-nodpi/default_wallpaper.jpgbin0 -> 224580 bytes
-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/Bluetooth/res/values/config.xml20
-rw-r--r--overlay/packages/apps/Launcher2/res/xml-sw720dp/default_workspace.xml57
-rw-r--r--overlay/packages/apps/Launcher2/res/xml/default_workspace.xml91
-rw-r--r--overlay/packages/apps/Launcher3/res/xml/default_workspace_5x6.xml69
-rw-r--r--overlay/packages/apps/SoundRecorder/res/values/styles.xml23
-rw-r--r--pixcir_tangoc.idc25
-rw-r--r--sepolicy/bluetooth.te1
-rw-r--r--sepolicy/device.te6
-rw-r--r--sepolicy/file.te2
-rw-r--r--sepolicy/file_contexts49
-rw-r--r--sepolicy/genfs_contexts1
-rw-r--r--sepolicy/init-cpuset-sh.te7
-rw-r--r--sepolicy/init.te11
-rw-r--r--sepolicy/kernel.te5
-rw-r--r--sepolicy/lad_dra7xx.te21
-rw-r--r--sepolicy/mediaserver.te12
-rw-r--r--sepolicy/netd.te8
-rw-r--r--sepolicy/pvr.te12
-rw-r--r--sepolicy/system_server.te2
-rw-r--r--sepolicy/ueventd.te3
-rw-r--r--sepolicy/vis.te20
-rw-r--r--system.prop2
-rw-r--r--tablet_core_hardware_am43xevm.xml37
-rw-r--r--temp.init.am43xevmboard.rcbin0 -> 12288 bytes
-rw-r--r--ueventd.am43xevmboard.rc32
-rw-r--r--vendorsetup.sh19
57 files changed, 5704 insertions, 0 deletions
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..270ceb1
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,36 @@
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),am43xevm)
29include $(CLEAR_VARS)
30
31# if some modules are built directly from this directory (not subdirectories),
32# their rules should be written here.
33
34include $(call all-makefiles-under,$(LOCAL_PATH))
35
36endif
diff --git a/AndroidProducts.mk b/AndroidProducts.mk
new file mode 100644
index 0000000..18e7b5d
--- /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_am43xevm.mk
diff --git a/BoardConfig.mk b/BoardConfig.mk
new file mode 100644
index 0000000..cbfe61b
--- /dev/null
+++ b/BoardConfig.mk
@@ -0,0 +1,86 @@
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
21OMAP_ENHANCEMENT := true
22
23ifeq ($(OMAP_ENHANCEMENT),true)
24COMMON_GLOBAL_CFLAGS += -DOMAP_ENHANCEMENT
25endif
26
27TARGET_CPU_ABI := armeabi-v7a
28TARGET_CPU_ABI2 := armeabi
29TARGET_CPU_SMP := true
30TARGET_ARCH := arm
31TARGET_ARCH_VARIANT := armv7-a-neon
32TARGET_CPU_VARIANT := cortex-a9
33
34ENABLE_CPUSETS := true
35
36BOARD_HAVE_BLUETOOTH := false
37BOARD_HAVE_BLUETOOTH_TI := false
38BOARD_BLUETOOTH_BDROID_BUILDCFG_INCLUDE_DIR := device/ti/am43xevm/bluetooth
39TARGET_NO_BOOTLOADER := true
40
41BOARD_KERNEL_BASE := 0x80008000
42#BOARD_KERNEL_CMDLINE := console=ttyO2,115200n8 mem=1024M androidboot.console=ttyO2 androidboot.hardware=am43xevmboard vram=20M omapfb.vram=0:16M
43BOARD_MKBOOTIMG_ARGS := --ramdisk_offset 0x03000000
44
45TARGET_NO_RADIOIMAGE := true
46TARGET_BOARD_PLATFORM := omap3
47TARGET_BOOTLOADER_BOARD_NAME := am43xevm
48
49BOARD_EGL_CFG := device/ti/am43xevm/egl.cfg
50
51USE_OPENGL_RENDERER := true
52
53TARGET_USERIMAGES_USE_EXT4 := true
54BOARD_SYSTEMIMAGE_PARTITION_SIZE := 805306368
55BOARD_USERDATAIMAGE_PARTITION_SIZE := 2147483648
56BOARD_CACHEIMAGE_PARTITION_SIZE := 268435456
57BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4
58BOARD_FLASH_BLOCK_SIZE := 4096
59
60TARGET_RECOVERY_FSTAB = device/ti/am43xevm/fstab.am43xevmboard
61TARGET_RECOVERY_PIXEL_FORMAT := "RGB565"
62TARGET_RELEASETOOLS_EXTENSIONS := device/ti/am43xevm
63
64# Connectivity - Wi-Fi
65USES_TI_MAC80211 := false
66ifeq ($(USES_TI_MAC80211),true)
67BOARD_WPA_SUPPLICANT_DRIVER := NL80211
68WPA_SUPPLICANT_VERSION := VER_0_8_X
69BOARD_HOSTAPD_DRIVER := NL80211
70BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_wl12xx
71BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_wl12xx
72BOARD_WLAN_DEVICE := wl12xx_mac80211
73BOARD_SOFTAP_DEVICE := wl12xx_mac80211
74COMMON_GLOBAL_CFLAGS += -DUSES_TI_MAC80211
75COMMON_GLOBAL_CFLAGS += -DANDROID_LIB_STUB
76endif
77
78BOARD_SEPOLICY_DIRS := device/ti/am43xevm/sepolicy
79
80# lidbrm driver
81BOARD_GPU_DRIVERS := omapdrm
82
83# DispSync vsync offsets in nanoseconds
84VSYNC_EVENT_PHASE_OFFSET_NS := 7500000
85SF_VSYNC_EVENT_PHASE_OFFSET_NS := 5000000
86
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/audio/Android.mk b/audio/Android.mk
new file mode 100644
index 0000000..4b34495
--- /dev/null
+++ b/audio/Android.mk
@@ -0,0 +1,22 @@
1# Copyright (C) 2015 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
17
18ifeq ($(APPE_AUDIO),true)
19include $(LOCAL_PATH)/hdmi/Android.mk
20else
21include $(call all-makefiles-under,$(LOCAL_PATH))
22endif
diff --git a/audio/audio_policy.conf b/audio/audio_policy.conf
new file mode 100644
index 0000000..f7a6f02
--- /dev/null
+++ b/audio/audio_policy.conf
@@ -0,0 +1,102 @@
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|AUDIO_DEVICE_IN_LINE
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 inputs {
69 a2dp {
70 sampling_rates 44100|48000
71 channel_masks AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO
72 formats AUDIO_FORMAT_PCM_16_BIT
73 devices AUDIO_DEVICE_IN_BLUETOOTH_A2DP
74 }
75 }
76 }
77 r_submix {
78 outputs {
79 r_submix {
80 sampling_rates 44100|48000
81 channel_masks AUDIO_CHANNEL_OUT_STEREO
82 formats AUDIO_FORMAT_PCM_16_BIT
83 devices AUDIO_DEVICE_OUT_REMOTE_SUBMIX
84 }
85 multichannel {
86 sampling_rates 44100|48000
87 channel_masks AUDIO_CHANNEL_OUT_5POINT1
88 formats AUDIO_FORMAT_PCM_16_BIT
89 devices AUDIO_DEVICE_OUT_REMOTE_SUBMIX
90 flags AUDIO_OUTPUT_FLAG_DIRECT
91 }
92 }
93 inputs {
94 r_submix {
95 sampling_rates 44100|48000
96 channel_masks AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO|AUDIO_CHANNEL_IN_5POINT1EMUL
97 formats AUDIO_FORMAT_PCM_16_BIT
98 devices AUDIO_DEVICE_IN_REMOTE_SUBMIX
99 }
100 }
101 }
102}
diff --git a/audio/hdmi/Android.mk b/audio/hdmi/Android.mk
new file mode 100644
index 0000000..976f84b
--- /dev/null
+++ b/audio/hdmi/Android.mk
@@ -0,0 +1,40 @@
1# Copyright (C) 2015 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 ($(TARGET_BOARD_PLATFORM), $(filter $(TARGET_BOARD_PLATFORM), am57x))
18
19include $(CLEAR_VARS)
20
21LOCAL_MODULE := audio.hdmi.$(TARGET_BOARD_PLATFORM)
22
23LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
24LOCAL_SRC_FILES := hdmi_audio_hw.c \
25 hdmi_audio_utils.c
26
27LOCAL_C_INCLUDES += \
28 external/tinyalsa/include \
29 external/libdrm \
30 external/libdrm/include/drm \
31 system/media/audio_utils/include \
32 system/media/audio_effects/include \
33 frameworks/native/include/media/openmax
34
35LOCAL_SHARED_LIBRARIES := liblog libcutils libtinyalsa libaudioutils libdl libdrm
36LOCAL_MODULE_TAGS := optional
37
38include $(BUILD_SHARED_LIBRARY)
39
40endif
diff --git a/audio/hdmi/hdmi_audio_hal.h b/audio/hdmi/hdmi_audio_hal.h
new file mode 100644
index 0000000..545e50e
--- /dev/null
+++ b/audio/hdmi/hdmi_audio_hal.h
@@ -0,0 +1,37 @@
1/* -*- mode: C; c-file-style: "stroustrup"; indent-tabs-mode: nil; -*- */
2/*
3 * Copyright (C) 2012 Texas Instruments
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17#ifndef TI_HDMI_AUDIO_HAL
18#define TI_HDMI_AUDIO_HAL
19
20typedef struct _hdmi_audio_caps {
21 int has_audio;
22 int speaker_alloc;
23} hdmi_audio_caps_t;
24
25/* Speaker allocation bits */
26#define CEA_SPKR_FLFR (1 << 0)
27#define CEA_SPKR_LFE (1 << 1)
28#define CEA_SPKR_FC (1 << 2)
29#define CEA_SPKR_RLRR (1 << 3)
30#define CEA_SPKR_RC (1 << 4)
31#define CEA_SPKR_FLCFRC (1 << 5)
32#define CEA_SPKR_RLCRRC (1 << 6)
33
34/* Defined in file hdmi_audio_utils.c */
35int hdmi_query_audio_caps(hdmi_audio_caps_t *caps);
36
37#endif /* TI_HDMI_AUDIO_HAL */
diff --git a/audio/hdmi/hdmi_audio_hw.c b/audio/hdmi/hdmi_audio_hw.c
new file mode 100644
index 0000000..1f5c520
--- /dev/null
+++ b/audio/hdmi/hdmi_audio_hw.c
@@ -0,0 +1,824 @@
1/* -*- mode: C; c-file-style: "stroustrup"; indent-tabs-mode: nil; -*- */
2/*
3 * Copyright (C) 2012 Texas Instruments
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#define LOG_TAG "hdmi_audio_hw"
19/* #define LOG_NDEBUG 0 */
20/* #define LOG_TRACE_FUNCTION */
21
22#ifndef LOG_TRACE_FUNCTION
23#define TRACE() ((void)0)
24#define TRACEM(fmt, ...) ((void)0)
25#else
26#define tfmt(x) x
27#define TRACE() (ALOGV("%s() %s:%d", __func__, __FILE__, __LINE__))
28#define TRACEM(fmt, ...) (ALOGV("%s() " tfmt(fmt) " %s:%d", __func__, ##__VA_ARGS__, __FILE__, __LINE__))
29#endif
30
31#include <errno.h>
32#include <pthread.h>
33#include <stdint.h>
34#include <sys/time.h>
35#include <stdlib.h>
36#include <stdio.h>
37
38#include <cutils/log.h>
39#include <cutils/str_parms.h>
40#include <cutils/properties.h>
41
42#include <hardware/hardware.h>
43#include <system/audio.h>
44#include <hardware/audio.h>
45
46#include <tinyalsa/asoundlib.h>
47
48#include <OMX_Audio.h>
49
50#include "hdmi_audio_hal.h"
51
52#define UNUSED(x) (void)(x)
53
54/* XXX TODO: Dynamically detect the HDMI card
55 * E.g. if a USB device is plugged in at boot time,
56 * it sometimes takes the card #1 slot and puts us
57 * on card #2.
58 */
59#define HDMI_PCM_CARD 1
60#define HDMI_PCM_DEV 0
61#define HDMI_SAMPLING_RATE 44100
62#define HDMI_PERIOD_SIZE 1920
63#define HDMI_PERIOD_COUNT 4
64#define HDMI_MAX_CHANNELS 8
65
66typedef struct _hdmi_device {
67 audio_hw_device_t device;
68 int map[HDMI_MAX_CHANNELS];
69 bool CEAMap;
70} hdmi_device_t;
71
72int cea_channel_map[HDMI_MAX_CHANNELS] = {OMX_AUDIO_ChannelLF,OMX_AUDIO_ChannelRF,OMX_AUDIO_ChannelLFE,
73 OMX_AUDIO_ChannelCF,OMX_AUDIO_ChannelLS,OMX_AUDIO_ChannelRS,
74 OMX_AUDIO_ChannelLR,OMX_AUDIO_ChannelRR}; /*Using OMX_AUDIO_CHANNELTYPE mapping*/
75
76typedef struct _hdmi_out {
77 audio_stream_out_t stream_out;
78 hdmi_device_t *dev;
79 struct pcm_config config;
80 struct pcm *pcm;
81 audio_config_t android_config;
82 int up;
83 void *buffcpy;
84} hdmi_out_t;
85
86#define S16_SIZE sizeof(int16_t)
87
88
89/*****************************************************************
90 * UTILITY FUNCTIONS
91 *****************************************************************
92 */
93
94/*****************************************************************
95 * AUDIO STREAM OUT (hdmi_out_*) DEFINITION
96 *****************************************************************
97 */
98
99uint32_t hdmi_out_get_sample_rate(const struct audio_stream *stream)
100{
101 hdmi_out_t *out = (hdmi_out_t*)stream;
102 struct pcm_config *config = &out->config;
103 TRACEM("stream=%p returning %d", stream, config->rate);
104 return config->rate;
105}
106
107/* DEPRECATED API */
108int hdmi_out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
109{
110 TRACE();
111 UNUSED(stream);
112 UNUSED(rate);
113
114 return -EINVAL;
115}
116
117/* Returns bytes for ONE PERIOD */
118size_t hdmi_out_get_buffer_size(const struct audio_stream *stream)
119{
120 const struct audio_stream_out *s = (const struct audio_stream_out *)stream;
121 hdmi_out_t *out = (hdmi_out_t*)stream;
122 struct pcm_config *config = &out->config;
123 size_t ans;
124
125 ans = audio_stream_out_frame_size(s) * config->period_size;
126
127 TRACEM("stream=%p returning %u", stream, ans);
128
129 return ans;
130}
131
132audio_channel_mask_t hdmi_out_get_channels(const struct audio_stream *stream)
133{
134 hdmi_out_t *out = (hdmi_out_t*)stream;
135 TRACEM("stream=%p returning %x", stream, out->android_config.channel_mask);
136 return out->android_config.channel_mask;
137}
138
139audio_format_t hdmi_out_get_format(const struct audio_stream *stream)
140{
141 hdmi_out_t *out = (hdmi_out_t*)stream;
142 TRACEM("stream=%p returning %x", stream, out->android_config.format);
143 return out->android_config.format;
144}
145
146/* DEPRECATED API */
147int hdmi_out_set_format(struct audio_stream *stream, audio_format_t format)
148{
149 TRACE();
150 UNUSED(stream);
151 UNUSED(format);
152
153 return -EINVAL;
154}
155
156int hdmi_out_standby(struct audio_stream *stream)
157{
158 hdmi_out_t *out = (hdmi_out_t*)stream;
159
160 TRACEM("stream=%p", stream);
161
162 if (out->up && out->pcm) {
163 out->up = 0;
164 pcm_close(out->pcm);
165 out->pcm = 0;
166 }
167
168 return 0;
169}
170
171int hdmi_out_dump(const struct audio_stream *stream, int fd)
172{
173 TRACE();
174 UNUSED(stream);
175 UNUSED(fd);
176
177 return 0;
178}
179
180audio_devices_t hdmi_out_get_device(const struct audio_stream *stream)
181{
182 TRACEM("stream=%p", stream);
183 UNUSED(stream);
184
185 return AUDIO_DEVICE_OUT_AUX_DIGITAL;
186}
187
188/* DEPRECATED API */
189int hdmi_out_set_device(struct audio_stream *stream, audio_devices_t device)
190{
191 TRACE();
192 UNUSED(stream);
193 UNUSED(device);
194
195 return 0;
196}
197
198int hdmi_out_set_parameters(struct audio_stream *stream, const char *kv_pairs)
199{
200 TRACEM("stream=%p kv_pairs='%s'", stream, kv_pairs);
201 UNUSED(stream);
202 UNUSED(kv_pairs);
203
204 return 0;
205}
206
207#define MASK_CEA_QUAD ( CEA_SPKR_FLFR | CEA_SPKR_RLRR )
208#define MASK_CEA_SURROUND ( CEA_SPKR_FLFR | CEA_SPKR_FC | CEA_SPKR_RC )
209#define MASK_CEA_5POINT1 ( CEA_SPKR_FLFR | CEA_SPKR_FC | CEA_SPKR_LFE | CEA_SPKR_RLRR )
210#define MASK_CEA_7POINT1 ( CEA_SPKR_FLFR | CEA_SPKR_FC | CEA_SPKR_LFE | CEA_SPKR_RLRR | CEA_SPKR_RLCRRC )
211#define SUPPORTS_ARR(spkalloc, profile) (((spkalloc) & (profile)) == (profile))
212
213char * hdmi_out_get_parameters(const struct audio_stream *stream,
214 const char *keys)
215{
216 struct str_parms *query = str_parms_create_str(keys);
217 char *str;
218 char value[256];
219 struct str_parms *reply = str_parms_create();
220 int status;
221 hdmi_audio_caps_t caps;
222
223 TRACEM("stream=%p keys='%s'", stream, keys);
224 UNUSED(stream);
225
226 if (hdmi_query_audio_caps(&caps)) {
227 ALOGE("Unable to get the HDMI audio capabilities");
228 str = calloc(1, 1);
229 goto end;
230 }
231
232 status = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS,
233 value, sizeof(value));
234 if (status >= 0) {
235 unsigned sa = caps.speaker_alloc;
236 bool first = true;
237
238 /* STEREO is intentionally skipped. This code is only
239 * executed for the 'DIRECT' interface, and we don't
240 * want stereo on a DIRECT thread.
241 */
242 value[0] = '\0';
243 if (SUPPORTS_ARR(sa, MASK_CEA_QUAD)) {
244 if (!first) {
245 strcat(value, "|");
246 }
247 first = false;
248 strcat(value, "AUDIO_CHANNEL_OUT_QUAD");
249 }
250 if (SUPPORTS_ARR(sa, MASK_CEA_SURROUND)) {
251 if (!first) {
252 strcat(value, "|");
253 }
254 first = false;
255 strcat(value, "AUDIO_CHANNEL_OUT_SURROUND");
256 }
257 if (SUPPORTS_ARR(sa, MASK_CEA_5POINT1)) {
258 if (!first) {
259 strcat(value, "|");
260 }
261 first = false;
262 strcat(value, "AUDIO_CHANNEL_OUT_5POINT1");
263 }
264 if (SUPPORTS_ARR(sa, MASK_CEA_7POINT1)) {
265 if (!first) {
266 strcat(value, "|");
267 }
268 first = false;
269 strcat(value, "AUDIO_CHANNEL_OUT_7POINT1");
270 }
271 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
272 str = strdup(str_parms_to_str(reply));
273 } else {
274 str = strdup(keys);
275 }
276
277 ALOGV("%s() reply: '%s'", __func__, str);
278
279end:
280 str_parms_destroy(query);
281 str_parms_destroy(reply);
282 return str;
283}
284int hdmi_out_add_audio_effect(const struct audio_stream *stream,
285 effect_handle_t effect)
286{
287 TRACE();
288 UNUSED(stream);
289 UNUSED(effect);
290
291 return 0;
292}
293int hdmi_out_remove_audio_effect(const struct audio_stream *stream,
294 effect_handle_t effect)
295{
296 TRACE();
297 UNUSED(stream);
298 UNUSED(effect);
299
300 return 0;
301}
302
303/* returns milliseconds */
304uint32_t hdmi_out_get_latency(const struct audio_stream_out *stream)
305{
306 uint32_t latency;
307 hdmi_out_t *out = (hdmi_out_t*)stream;
308 struct pcm_config *config = &out->config;
309
310 TRACEM("stream=%p", stream);
311
312 return (1000 * config->period_size * config->period_count) / config->rate;
313}
314
315int hdmi_out_set_volume(struct audio_stream_out *stream, float left, float right)
316{
317 TRACE();
318 UNUSED(stream);
319 UNUSED(left);
320 UNUSED(right);
321
322 return -ENOSYS;
323}
324
325static int hdmi_out_open_pcm(hdmi_out_t *out)
326{
327 int card = HDMI_PCM_CARD;
328 int dev = HDMI_PCM_DEV;
329 int ret;
330
331 TRACEM("out=%p", out);
332
333 /* out->up must be 0 (down) */
334 if (out->up) {
335 ALOGE("Trying to open a PCM that's already up. "
336 "This will probably deadlock... so aborting");
337 return 0;
338 }
339
340 out->pcm = pcm_open(card, dev, PCM_OUT, &out->config);
341
342 if(out->pcm && pcm_is_ready(out->pcm)) {
343 out->up = 1;
344 ret = 0;
345 } else {
346 ALOGE("cannot open HDMI pcm card %d dev %d error: %s",
347 card, dev, pcm_get_error(out->pcm));
348 pcm_close(out->pcm);
349 out->pcm = 0;
350 out->up = 0;
351 ret = 1;
352 }
353
354 return ret;
355}
356
357void channel_remap(struct audio_stream_out *stream, const void *buffer,
358 size_t bytes)
359{
360 hdmi_out_t *out = (hdmi_out_t*)stream;
361 hdmi_device_t *adev = out->dev;
362 int x, y, frames;
363 int16_t *buf = (int16_t *)buffer;
364 int16_t *tmp_buf = (int16_t *)out->buffcpy;
365
366 frames = bytes / audio_stream_out_frame_size(stream);
367 while (frames--){
368 for(y = 0; y < (int)out->config.channels; y++){
369 for(x = 0; x < (int)out->config.channels; x++){
370 if (cea_channel_map[y] == adev->map[x]){
371 tmp_buf[y] = buf[x];
372 break;
373 }
374 }
375 }
376 tmp_buf += (int)out->config.channels;
377 buf += (int)out->config.channels;
378 }
379}
380
381ssize_t hdmi_out_write(struct audio_stream_out *stream, const void* buffer,
382 size_t bytes)
383{
384 hdmi_out_t *out = (hdmi_out_t*)stream;
385 hdmi_device_t *adev = out->dev;
386 ssize_t ret;
387
388 TRACEM("stream=%p buffer=%p bytes=%d", stream, buffer, bytes);
389
390 if (!out->up) {
391 if(hdmi_out_open_pcm(out)) {
392 ret = -ENOSYS;
393 goto exit;
394 }
395 }
396
397 if (out->config.channels > 2 && !adev->CEAMap){
398 channel_remap(stream, buffer, bytes);
399 ret = pcm_write(out->pcm, out->buffcpy, bytes);
400 } else {
401 ret = pcm_write(out->pcm, buffer, bytes);
402 }
403exit:
404 if (ret != 0) {
405 ALOGE("Error writing to HDMI pcm: %s",
406 out->pcm ? pcm_get_error(out->pcm) : "failed to open PCM device");
407 hdmi_out_standby((struct audio_stream*)stream);
408 unsigned int usecs = bytes * 1000000 /
409 audio_stream_out_frame_size(stream) /
410 hdmi_out_get_sample_rate((struct audio_stream*)stream);
411 if (usecs >= 1000000L) {
412 usecs = 999999L;
413 }
414 usleep(usecs);
415 }
416
417 return bytes;
418}
419
420
421int hdmi_out_get_render_position(const struct audio_stream_out *stream,
422 uint32_t *dsp_frames)
423{
424 TRACE();
425 UNUSED(stream);
426 UNUSED(dsp_frames);
427
428 return -EINVAL;
429}
430
431int hdmi_out_get_next_write_timestamp(const struct audio_stream_out *stream,
432 int64_t *timestamp)
433{
434 TRACE();
435 UNUSED(stream);
436 UNUSED(timestamp);
437
438 return -EINVAL;
439}
440
441
442
443audio_stream_out_t hdmi_stream_out_descriptor = {
444 .common = {
445 .get_sample_rate = hdmi_out_get_sample_rate,
446 .set_sample_rate = hdmi_out_set_sample_rate,
447 .get_buffer_size = hdmi_out_get_buffer_size,
448 .get_channels = hdmi_out_get_channels,
449 .get_format = hdmi_out_get_format,
450 .set_format = hdmi_out_set_format,
451 .standby = hdmi_out_standby,
452 .dump = hdmi_out_dump,
453 .get_device = hdmi_out_get_device,
454 .set_device = hdmi_out_set_device,
455 .set_parameters = hdmi_out_set_parameters,
456 .get_parameters = hdmi_out_get_parameters,
457 .add_audio_effect = hdmi_out_add_audio_effect,
458 .remove_audio_effect = hdmi_out_remove_audio_effect,
459 },
460 .get_latency = hdmi_out_get_latency,
461 .set_volume = hdmi_out_set_volume,
462 .write = hdmi_out_write,
463 .get_render_position = hdmi_out_get_render_position,
464 .get_next_write_timestamp = hdmi_out_get_next_write_timestamp,
465};
466
467/*****************************************************************
468 * AUDIO DEVICE (hdmi_adev_*) DEFINITION
469 *****************************************************************
470 */
471
472static int hdmi_adev_close(struct hw_device_t *device)
473{
474 TRACE();
475 UNUSED(device);
476
477 return 0;
478}
479
480static uint32_t hdmi_adev_get_supported_devices(const audio_hw_device_t *dev)
481{
482 TRACE();
483 UNUSED(dev);
484
485 return AUDIO_DEVICE_OUT_AUX_DIGITAL;
486}
487
488static int hdmi_adev_init_check(const audio_hw_device_t *dev)
489{
490 TRACE();
491 UNUSED(dev);
492
493 return 0;
494}
495
496static int hdmi_adev_set_voice_volume(audio_hw_device_t *dev, float volume)
497{
498 TRACE();
499 UNUSED(dev);
500 UNUSED(volume);
501
502 return -ENOSYS;
503}
504
505static int hdmi_adev_set_master_volume(audio_hw_device_t *dev, float volume)
506{
507 TRACE();
508 UNUSED(dev);
509 UNUSED(volume);
510
511 return -ENOSYS;
512}
513
514static int hdmi_adev_get_master_volume(audio_hw_device_t *dev, float *volume)
515{
516 TRACE();
517 UNUSED(dev);
518 UNUSED(volume);
519
520 return -ENOSYS;
521}
522
523static int hdmi_adev_set_mode(audio_hw_device_t *dev, audio_mode_t mode)
524{
525 TRACE();
526 UNUSED(dev);
527 UNUSED(mode);
528
529 return 0;
530}
531
532static int hdmi_adev_set_mic_mute(audio_hw_device_t *dev, bool state)
533{
534 TRACE();
535 UNUSED(dev);
536 UNUSED(state);
537
538 return -ENOSYS;
539}
540
541static int hdmi_adev_get_mic_mute(const audio_hw_device_t *dev, bool *state)
542{
543 TRACE();
544 UNUSED(dev);
545 UNUSED(state);
546
547 return -ENOSYS;
548}
549
550static int hdmi_adev_set_parameters(audio_hw_device_t *dev, const char *kv_pairs)
551{
552 TRACEM("dev=%p kv_pairss='%s'", dev, kv_pairs);
553
554 struct str_parms *params;
555 char *str;
556 char value[HDMI_MAX_CHANNELS];
557 int ret, x, val, numMatch = 0;
558 hdmi_device_t *adev = (hdmi_device_t *)dev;
559
560 params = str_parms_create_str(kv_pairs);
561 //Handle maximum of 8 channels
562 ret = str_parms_get_str(params, "channel_map", value, HDMI_MAX_CHANNELS);
563 if (ret >= 0) {
564 val = strtol(value, NULL, 10);
565 for(x = 0; x < HDMI_MAX_CHANNELS; x++) {
566 adev->map[x] = (val & (0xF << x*4)) >> x*4;
567 if (adev->map[x] == cea_channel_map[x])
568 numMatch += 1;
569 }
570 if (numMatch >= 5)
571 adev->CEAMap = true;
572 else
573 adev->CEAMap = false;
574 }
575 return 0;
576}
577
578static char* hdmi_adev_get_parameters(const audio_hw_device_t *dev,
579 const char *keys)
580{
581 TRACEM("dev=%p keys='%s'", dev, keys);
582 UNUSED(dev);
583 UNUSED(keys);
584
585 return NULL;
586}
587
588static size_t hdmi_adev_get_input_buffer_size(const audio_hw_device_t *dev,
589 const struct audio_config *config)
590{
591 TRACE();
592 UNUSED(dev);
593 UNUSED(config);
594
595 return 0;
596}
597
598#define DUMP_FLAG(flags, flag) { \
599 if ((flags) & (flag)) { \
600 ALOGV("set: " #flag); \
601 } else { \
602 ALOGV("unset: " #flag); \
603 } \
604 }
605
606static int hdmi_adev_open_output_stream(audio_hw_device_t *dev,
607 audio_io_handle_t handle,
608 audio_devices_t devices,
609 audio_output_flags_t flags,
610 struct audio_config *config,
611 struct audio_stream_out **stream_out,
612 const char *address)
613{
614 hdmi_out_t *out = 0;
615 struct pcm_config *pcm_config = 0;
616 struct audio_config *a_config = 0;
617
618 TRACE();
619 UNUSED(handle);
620 UNUSED(devices);
621 UNUSED(flags);
622 UNUSED(address);
623
624 out = calloc(1, sizeof(hdmi_out_t));
625 if (!out) {
626 return -ENOMEM;
627 }
628
629 out->dev = (hdmi_device_t *)dev;
630 memcpy(&out->stream_out, &hdmi_stream_out_descriptor,
631 sizeof(audio_stream_out_t));
632 memcpy(&out->android_config, config, sizeof(audio_config_t));
633
634 pcm_config = &out->config;
635 a_config = &out->android_config;
636
637#if defined(LOG_NDEBUG) && (LOG_NDEBUG == 0)
638 /* Analyze flags */
639 if (flags) {
640 DUMP_FLAG(flags, AUDIO_OUTPUT_FLAG_DIRECT)
641 DUMP_FLAG(flags, AUDIO_OUTPUT_FLAG_PRIMARY)
642 DUMP_FLAG(flags, AUDIO_OUTPUT_FLAG_FAST)
643 DUMP_FLAG(flags, AUDIO_OUTPUT_FLAG_DEEP_BUFFER)
644 } else {
645 ALOGV("flags == AUDIO_OUTPUT_FLAG_NONE (0)");
646 }
647#endif /* defined(LOG_NDEBUG) && (LOG_NDEBUG == 0) */
648 /* Initialize the PCM Configuration */
649 pcm_config->period_size = HDMI_PERIOD_SIZE;
650 pcm_config->period_count = HDMI_PERIOD_COUNT;
651
652 if (a_config->sample_rate) {
653 pcm_config->rate = config->sample_rate;
654 } else {
655 pcm_config->rate = HDMI_SAMPLING_RATE;
656 a_config->sample_rate = HDMI_SAMPLING_RATE;
657 }
658
659 switch (a_config->format) {
660 case AUDIO_FORMAT_DEFAULT:
661 a_config->format = AUDIO_FORMAT_PCM_16_BIT;
662 /* fall through */
663 case AUDIO_FORMAT_PCM_16_BIT:
664 pcm_config->format = PCM_FORMAT_S16_LE;
665 break;
666 default:
667 ALOGE("HDMI rejecting format %x", config->format);
668 goto fail;
669 }
670
671 a_config->channel_mask = config->channel_mask;
672 switch (config->channel_mask) {
673 case AUDIO_CHANNEL_OUT_STEREO:
674 pcm_config->channels = 2;
675 break;
676 case AUDIO_CHANNEL_OUT_QUAD:
677 pcm_config->channels = 4;
678 break;
679 case AUDIO_CHANNEL_OUT_5POINT1:
680 pcm_config->channels = 6;
681 break;
682 case AUDIO_CHANNEL_OUT_7POINT1:
683 pcm_config->channels = 8;
684 break;
685 default:
686 ALOGE("HDMI setting a default channel_mask %x -> 8", config->channel_mask);
687 config->channel_mask = AUDIO_CHANNEL_OUT_7POINT1;
688 a_config->channel_mask = AUDIO_CHANNEL_OUT_7POINT1;
689 pcm_config->channels = 8;
690 }
691
692 //Allocating buffer for at most 8 channels
693 out->buffcpy = malloc(pcm_config->period_size * sizeof(int16_t) * HDMI_MAX_CHANNELS);
694 if (!out->buffcpy){
695 ALOGE("Could not allocate memory");
696 goto fail;
697 }
698
699 ALOGV("stream = %p", out);
700 *stream_out = &out->stream_out;
701
702 return 0;
703
704fail:
705 free(out);
706 return -ENOSYS;
707}
708
709static void hdmi_adev_close_output_stream(audio_hw_device_t *dev,
710 struct audio_stream_out* stream_out)
711{
712 hdmi_out_t *out = (hdmi_out_t*)stream_out;
713
714 TRACEM("dev=%p stream_out=%p", dev, stream_out);
715 UNUSED(dev);
716
717 stream_out->common.standby((audio_stream_t*)stream_out);
718 free(out->buffcpy);
719 out->buffcpy = NULL;
720 free(stream_out);
721}
722
723static int hdmi_adev_open_input_stream(audio_hw_device_t *dev,
724 audio_io_handle_t handle,
725 audio_devices_t devices,
726 struct audio_config *config,
727 struct audio_stream_in **stream_in,
728 audio_input_flags_t flags,
729 const char *address,
730 audio_source_t source)
731{
732 TRACE();
733 UNUSED(dev);
734 UNUSED(handle);
735 UNUSED(devices);
736 UNUSED(config);
737 UNUSED(stream_in);
738 UNUSED(flags);
739 UNUSED(address);
740 UNUSED(source);
741
742 return -ENOSYS;
743}
744
745static void hdmi_adev_close_input_stream(audio_hw_device_t *dev,
746 struct audio_stream_in *stream_in)
747{
748 TRACE();
749 UNUSED(dev);
750 UNUSED(stream_in);
751}
752
753static int hdmi_adev_dump(const audio_hw_device_t *dev, int fd)
754{
755 TRACE();
756 UNUSED(dev);
757 UNUSED(fd);
758
759 return 0;
760}
761
762static hdmi_device_t hdmi_adev = {
763 .device = {
764 .common = {
765 .tag = HARDWARE_DEVICE_TAG,
766 .version = AUDIO_DEVICE_API_VERSION_2_0,
767 .module = NULL,
768 .close = hdmi_adev_close,
769 },
770 .get_supported_devices = hdmi_adev_get_supported_devices,
771 .init_check = hdmi_adev_init_check,
772 .set_voice_volume = hdmi_adev_set_voice_volume,
773 .set_master_volume = hdmi_adev_set_master_volume,
774 .get_master_volume = hdmi_adev_get_master_volume,
775 .set_mode = hdmi_adev_set_mode,
776 .set_mic_mute = hdmi_adev_set_mic_mute,
777 .get_mic_mute = hdmi_adev_get_mic_mute,
778 .set_parameters = hdmi_adev_set_parameters,
779 .get_parameters = hdmi_adev_get_parameters,
780 .get_input_buffer_size = hdmi_adev_get_input_buffer_size,
781 .open_output_stream = hdmi_adev_open_output_stream,
782 .close_output_stream = hdmi_adev_close_output_stream,
783 .open_input_stream = hdmi_adev_open_input_stream,
784 .close_input_stream = hdmi_adev_close_input_stream,
785 .dump = hdmi_adev_dump,
786 },
787
788 // Don't reorder channels until a valid CEA mapping has been
789 // explicitly set. IOW, assume default channel mapping is
790 // fine until some other mapping is requested.
791 .CEAMap = true,
792 .map = {0},
793};
794
795static int hdmi_adev_open(const hw_module_t* module,
796 const char* name,
797 hw_device_t** device)
798{
799 TRACE();
800
801 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
802 return -EINVAL;
803
804 hdmi_adev.device.common.module = (struct hw_module_t *) module;
805 *device = &hdmi_adev.device.common;
806
807 return 0;
808}
809
810static struct hw_module_methods_t hal_module_methods = {
811 .open = hdmi_adev_open,
812};
813
814struct audio_module HAL_MODULE_INFO_SYM = {
815 .common = {
816 .tag = HARDWARE_MODULE_TAG,
817 .version_major = 1,
818 .version_minor = 0,
819 .id = AUDIO_HARDWARE_MODULE_ID,
820 .name = "OMAP HDMI audio HW HAL",
821 .author = "Texas Instruments",
822 .methods = &hal_module_methods,
823 },
824};
diff --git a/audio/hdmi/hdmi_audio_utils.c b/audio/hdmi/hdmi_audio_utils.c
new file mode 100644
index 0000000..b29ec25
--- /dev/null
+++ b/audio/hdmi/hdmi_audio_utils.c
@@ -0,0 +1,414 @@
1/* -*- mode: C; c-file-style: "stroustrup"; indent-tabs-mode: nil; -*- */
2/*
3 * Copyright (C) 2012 Texas Instruments
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#define LOG_TAG "hdmi_audio_caps"
19/* #define LOG_NDEBUG 0 */
20
21#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <string.h>
25#include <errno.h>
26
27#include <xf86drm.h>
28#include <xf86drmMode.h>
29
30#include "hdmi_audio_hal.h"
31
32/*
33 * This program can be compiled standalone for debugging and
34 * testing by defining HDMI_CAPS_STANDALONE
35 */
36
37#ifdef HDMI_CAPS_STANDALONE
38#include <stdio.h>
39
40#define lfmt(x) x
41#define ALOGV(fmt, ...) printf(lfmt(fmt) "\n", ##__VA_ARGS__)
42#define ALOGW(fmt, ...) printf(lfmt(fmt) "\n", ##__VA_ARGS__)
43#define ALOGE(fmt, ...) printf(lfmt(fmt) "\n", ##__VA_ARGS__)
44#define ALOGV_IF(cond, fmt, ...) { if (cond) { printf(lfmt(fmt) "\n", ##__VA_ARGS__); } }
45#define ALOGE_IF(cond, fmt, ...) { if (cond) { printf(lfmt(fmt) "\n", ##__VA_ARGS__); } }
46#else /* HDMI_CAPS_STANDALONE */
47
48#include <cutils/log.h>
49
50#endif /* HDMI_CAPS_STANDALONE */
51
52/*****************************************************************
53 * HDMI AUDIO CAPABILITIES (EDID PARSING)
54 *
55 * To maintain this section, you need these references:
56 *
57 * - High-Definition Multimedia Interface Specification Version 1.4a
58 * Mar 4, 2010, Hitachi et al. (See Section 8.3 "E-EDID Data
59 * Structure")
60 *
61 * - E-EDID, VESA Enhanced Extended Display Identification Data
62 * Standard, Release A, Revision 2, September 25. 2006,
63 * Video Electronics Standards Association (VESA)
64 *
65 * - CEA-861-D, A DTV Profile for Uncompressed High Speed Digital
66 * Interfaces, July 2006 (Section 7.5)
67 *
68 *
69 * Summary: The E-EDID is composed of 128-byte blocks. The first byte
70 * identifies the block. HDMI devices are required to send a CEA
71 * Extension block (version 3), and the first one is the one we /must/
72 * parse. (You can probably go far with just this info and the
73 * CEA-861-D spec.)
74 *
75 *****************************************************************
76 */
77
78#define DISPLAY_MAX 3
79#define DISPLAY_NAME_MAX 20
80#define HDMI_DISPLAY_NAME "hdmi"
81#define OMAP_DSS_SYSFS "/sys/devices/platform/omapdss/"
82#define DRM_OMAP_DEVNAME "omapdrm"
83#define DRM_EDID_PROPNAME "EDID"
84
85/* TODO: Figure this out dynamically, but ATM this is enforced
86 * in the kernel.
87 */
88#define HDMI_MAX_EDID 512
89
90#define EDID_BLOCK_SIZE 128
91#define EDID_BLOCK_MAP_ID 0xF0
92#define EDID_BLOCK_CEA_ID 0x02
93#define EDID_BLOCK_CEA_REV_3 0x03
94
95#define CEA_TAG_MASK 0xE0
96#define CEA_SIZE_MASK 0x1F
97#define CEA_TAG_AUDIO (1 << 5)
98#define CEA_TAG_VIDEO (2 << 5)
99#define CEA_TAG_SPKRS (4 << 5)
100#define CEA_BIT_AUDIO (1 << 6)
101
102static void hdmi_dump_short_audio_descriptor_block(unsigned char *mem)
103{
104 const unsigned char FORMAT_MASK = 0x78;
105 const unsigned char MAX_CH_MASK = 0x07;
106 int n, size;
107 unsigned char *p, *end, byte, format, chs;
108 const char* formats[] = {
109 "Reserved (0)",
110 "LPCM",
111 "AC-3",
112 "MPEG1 (Layers 1 & 2)",
113 "MP3 (MPEG1 Layer 3)",
114 "MPEG2 (multichannel)",
115 "AAC",
116 "DTS",
117 "ATRAC",
118 "One Bit Audio",
119 "Dolby Digital +",
120 "DTS-HD",
121 "MAT (MLP)",
122 "DST",
123 "WMA Pro",
124 "Reserved (15)",
125 };
126
127 size = *mem & CEA_SIZE_MASK;
128 end = mem + 1 + size;
129
130 for (p = mem + 1 ; p < end ; p += 3) {
131 byte = p[0];
132 format = (byte & FORMAT_MASK) >> 3;
133 chs = byte & MAX_CH_MASK;
134
135 ALOGV("Parsing Short Audio Descriptor:");
136 ALOGV(" format: %s", formats[format]);
137 ALOGV(" max channels: %d", chs + 1);
138 ALOGV(" sample rates:");
139
140 byte = p[1];
141 ALOGV_IF(byte & (1 << 0), " 32.0 kHz");
142 ALOGV_IF(byte & (1 << 1), " 44.1 kHz");
143 ALOGV_IF(byte & (1 << 2), " 48.0 kHz");
144 ALOGV_IF(byte & (1 << 3), " 88.2 kHz");
145 ALOGV_IF(byte & (1 << 4), " 96.0 kHz");
146 ALOGV_IF(byte & (1 << 5), " 176.4 kHz");
147 ALOGV_IF(byte & (1 << 6), " 192.0 kHz");
148
149 byte = p[2];
150 if ((format >= 2) && (format <= 8)) {
151 ALOGV(" max bit rate: %d kHz", ((int)byte) * 8);
152 }
153 }
154}
155
156int hdmi_get_edid_sysfs(unsigned char *edid)
157{
158 int fd;
159 char fn[256];
160 char disp_name[DISPLAY_NAME_MAX];
161 int status;
162 int index, n;
163
164 ALOGI("Trying to read the HDMI EDID through sysfs");
165
166 for (index = 0; index < DISPLAY_MAX; index++) {
167 snprintf(fn, sizeof(fn), OMAP_DSS_SYSFS "display%u", index);
168 fd = open(fn, O_RDONLY);
169 if (fd < 0) {
170 ALOGE("HDMI sysfs entry not found");
171 return -ENODEV;
172 }
173 close(fd);
174
175 snprintf(fn, sizeof(fn), OMAP_DSS_SYSFS "display%u/name", index);
176 fd = open(fn, O_RDONLY);
177 if (fd < 0) {
178 ALOGE("Error opening display name sysfs entry");
179 return -ENODEV;
180 }
181
182 status = read(fd, disp_name, sizeof(disp_name));
183 close(fd);
184 if (status == -1) {
185 ALOGE("Error reading display name sysfs entry");
186 return -errno;
187 }
188
189 if (!strncasecmp(disp_name, HDMI_DISPLAY_NAME, strlen(HDMI_DISPLAY_NAME))) {
190 ALOGV("HDMI device found at display%u", index);
191 break;
192 }
193 }
194
195 if (index == DISPLAY_MAX) {
196 ALOGE("HDMI sysfs entry not found");
197 return -ENODEV;
198 }
199
200 snprintf(fn, sizeof(fn), OMAP_DSS_SYSFS "display%u/edid", index);
201 fd = open(fn, O_RDONLY);
202 if (fd == -1) {
203 return -errno;
204 }
205
206 memset(edid, 0, HDMI_MAX_EDID);
207
208 status = read(fd, edid, HDMI_MAX_EDID);
209 close(fd);
210 if (status == -1) {
211 ALOGV("Error reading EDID through sysfs");
212 return -errno;
213 } else {
214 ALOGV("read %d bytes from edid sysfs file", status);
215 }
216
217 return 0;
218}
219
220int hdmi_get_edid_drm(unsigned char *edid)
221{
222 drmModeRes *resources;
223 drmModeConnector *connector;
224 drmModePropertyPtr prop;
225 drmModePropertyBlobPtr blob;
226 unsigned char *blob_data;
227 int fd, i, j;
228 int found = 0;
229
230 ALOGI("Trying to read the HDMI EDID through DRM");
231
232 fd = drmOpen(DRM_OMAP_DEVNAME, NULL);
233 if (fd < 0) {
234 ALOGE("Failed to open DRM device '%s'", DRM_OMAP_DEVNAME);
235 return -ENODEV;
236 }
237
238 resources = drmModeGetResources(fd);
239 if (!resources) {
240 ALOGE("Failed to get DRM resources");
241 drmClose(fd);
242 return -EINVAL;
243 }
244
245 for (i = 0; (i < resources->count_connectors) && !found; i++) {
246 connector = drmModeGetConnector(fd, resources->connectors[i]);
247 if (!connector) {
248 continue;
249 }
250
251 if (!connector->count_modes) {
252 drmModeFreeConnector(connector);
253 continue;
254 }
255
256 for (j = 0; (j < connector->count_props) && !found; j++) {
257 prop = drmModeGetProperty(fd, connector->props[j]);
258 if (!prop) {
259 continue;
260 }
261
262 if (strcmp(prop->name, DRM_EDID_PROPNAME) ||
263 !(prop->flags & DRM_MODE_PROP_BLOB)) {
264 drmModeFreeProperty(prop);
265 continue;
266 }
267
268 blob = drmModeGetPropertyBlob(fd, connector->prop_values[j]);
269 if (!blob) {
270 drmModeFreeProperty(prop);
271 continue;
272 }
273
274 if (blob->length > HDMI_MAX_EDID) {
275 ALOGW("EDID blob length %u is larger than expected %d, skipping",
276 blob->length, HDMI_MAX_EDID);
277 drmModeFreePropertyBlob(blob);
278 drmModeFreeProperty(prop);
279 continue;
280 }
281
282 ALOGV("EDID has been found, length is %u bytes", blob->length);
283 memset(edid, 0, HDMI_MAX_EDID);
284 memcpy(edid, blob->data, blob->length);
285 drmModeFreePropertyBlob(blob);
286 drmModeFreeProperty(prop);
287 found = 1;
288 }
289
290 drmModeFreeConnector(connector);
291 }
292
293 drmModeFreeResources(resources);
294
295 drmClose(fd);
296
297 return found ? 0 : -ENODEV;
298}
299
300int hdmi_query_audio_caps(hdmi_audio_caps_t *caps)
301{
302 unsigned char edid[HDMI_MAX_EDID];
303 int index, n;
304 int nblocks;
305 int edid_size;
306 int has_audio = 0;
307 int speaker_alloc = 0;
308 int done = 0;
309 int status;
310
311 status = hdmi_get_edid_sysfs(edid);
312 if (status) {
313 ALOGE("Failed to read EDID through sysfs");
314 status = hdmi_get_edid_drm(edid);
315 if (status) {
316 ALOGE("Failed to read EDID through DRM");
317 return status;
318 }
319 }
320
321 nblocks = edid[0x7E];
322 if (edid[EDID_BLOCK_SIZE] == EDID_BLOCK_MAP_ID) {
323 /* The block map is just an index... don't need it. */
324 ++nblocks;
325 }
326 ALOGV("EDID contians %d additional extension block(s)", nblocks);
327 edid_size = EDID_BLOCK_SIZE * (nblocks + 1);
328 if (edid_size > HDMI_MAX_EDID) {
329 edid_size = HDMI_MAX_EDID;
330 }
331
332 for (index = EDID_BLOCK_SIZE ; index < edid_size ; index += EDID_BLOCK_SIZE) {
333 if ((edid[index] == EDID_BLOCK_CEA_ID)
334 && (edid[index+1] == EDID_BLOCK_CEA_REV_3)) {
335 /* CEA BLOCK */
336 unsigned char d;
337 unsigned char byte, tag, size;
338
339 /* Parse CEA header for size and audio presence */
340 d = edid[index + 2];
341 if (edid[index + 3] & CEA_BIT_AUDIO) {
342 has_audio = 1;
343 } else {
344 break;
345 }
346
347 n = 4;
348 while (n < d) {
349 byte = edid[index + n];
350 tag = byte & CEA_TAG_MASK;
351 size = byte & CEA_SIZE_MASK;
352 ++n;
353
354 switch (tag) {
355 case CEA_TAG_AUDIO:
356 /* ignore for now, needed for bitstream. */
357 hdmi_dump_short_audio_descriptor_block(&edid[index + n - 1]);
358 break;
359 case CEA_TAG_SPKRS: /* I think this fails... not sure why */
360 ALOGE_IF(size != 3, "CEA Speaker Allocation Block is wrong size "
361 "(got %d, expected 3)", size);
362 byte = edid[index + n];
363 speaker_alloc = byte;
364 break;
365 }
366
367 n += size;
368 }
369
370 /* Per spec, only need to parse the first block */
371 break;
372 }
373 }
374
375 caps->has_audio = has_audio;
376 caps->speaker_alloc = speaker_alloc;
377
378 ALOGI_IF(caps->has_audio, "HDMI speaker allocation 0x%02x",
379 caps->speaker_alloc);
380
381 ALOGW_IF(!caps->has_audio, "HDMI device doesn't support audio");
382
383 return 0;
384}
385
386
387#ifdef HDMI_CAPS_STANDALONE
388int main(int argc, char* argv[])
389{
390 const char prog_name[] = "hdmi_audio_caps";
391 hdmi_audio_caps_t caps = {
392 .has_audio = 0,
393 };
394
395 if (argc < 1) {
396 printf("usage: %s\n", argc ? argv[0] : prog_name);
397 return 0;
398 }
399
400 if (hdmi_query_audio_caps(&caps)) {
401 fprintf(stderr, "Fatal error: could not read EDID (%s)\n",
402 strerror(errno));
403 return 1;
404 }
405
406 printf("\n");
407 printf("caps = {\n");
408 printf(" .has_audio = %d\n", caps.has_audio);
409 printf(" .speaker_alloc = 0x%02x\n", caps.speaker_alloc);
410 printf("}\n");
411
412 return 0;
413}
414#endif /* HDMI_CAPS_STANDALONE */
diff --git a/audio/primary/Android.mk b/audio/primary/Android.mk
new file mode 100644
index 0000000..40f60da
--- /dev/null
+++ b/audio/primary/Android.mk
@@ -0,0 +1,43 @@
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 am57x, $(TARGET_BOARD_PLATFORM)),am57x)
18
19include $(CLEAR_VARS)
20
21LOCAL_MODULE := audio.primary.$(TARGET_BOARD_PLATFORM)
22
23LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
24LOCAL_SRC_FILES := audio_hw.c
25
26LOCAL_C_INCLUDES += \
27 external/tinyalsa/include \
28 system/media/audio_route/include \
29 system/media/audio_utils/include \
30 system/media/audio_effects/include
31
32LOCAL_SHARED_LIBRARIES := \
33 liblog \
34 libcutils \
35 libtinyalsa \
36 libaudioroute \
37 libaudioutils
38
39LOCAL_MODULE_TAGS := optional
40
41include $(BUILD_SHARED_LIBRARY)
42
43endif
diff --git a/audio/primary/audio_hw.c b/audio/primary/audio_hw.c
new file mode 100644
index 0000000..95f0f06
--- /dev/null
+++ b/audio/primary/audio_hw.c
@@ -0,0 +1,1770 @@
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#define UNUSED(x) (void)(x)
45
46/* yet another definition of ARRAY_SIZE macro) */
47#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
48
49/*
50 * additional space in resampler buffer allowing for extra samples to be returned
51 * by speex resampler when sample rates ratio is not an integer
52 */
53#define RESAMPLER_HEADROOM_FRAMES 10
54
55/* buffer_remix: functor for doing in-place buffer manipulations.
56 *
57 * NB. When remix_func is called, the memory at `buf` must be at least
58 * as large as frames * sample_size * MAX(in_chans, out_chans).
59 */
60struct buffer_remix {
61 void (*remix_func)(struct buffer_remix *data, void *buf, size_t frames);
62 size_t sample_size; /* size of one audio sample, in bytes */
63 size_t in_chans; /* number of input channels */
64 size_t out_chans; /* number of output channels */
65};
66
67struct j6_voice_stream {
68 struct j6_audio_device *dev;
69 struct pcm *pcm_in;
70 struct pcm *pcm_out;
71 struct pcm_config in_config;
72 struct pcm_config out_config;
73 struct resampler_itfe *resampler;
74 struct resampler_buffer_provider buf_provider;
75 struct buffer_remix *remix;
76 pthread_t thread;
77 int16_t *in_buffer;
78 int16_t *out_buffer;
79 size_t in_frames;
80 size_t out_frames;
81 size_t in_frame_size;
82 size_t out_frame_size;
83 char *name;
84};
85
86struct j6_voice {
87 struct j6_voice_stream ul;
88 struct j6_voice_stream dl;
89};
90
91struct j6_audio_device {
92 struct audio_hw_device device;
93 struct j6_stream_in *in;
94 struct j6_stream_out *out;
95 struct j6_voice voice;
96 struct audio_route *route;
97 audio_devices_t in_device;
98 audio_devices_t out_device;
99 pthread_mutex_t lock;
100 unsigned int card;
101 unsigned int in_port;
102 unsigned int out_port;
103 unsigned int bt_card;
104 unsigned int bt_port;
105 bool mic_mute;
106 bool in_call;
107 audio_mode_t mode;
108};
109
110struct j6_stream_in {
111 struct audio_stream_in stream;
112 struct j6_audio_device *dev;
113 struct pcm_config config;
114 struct pcm *pcm;
115 struct buffer_remix *remix; /* adapt hw chan count to client */
116 struct resampler_itfe *resampler;
117 struct resampler_buffer_provider buf_provider;
118 int16_t *buffer;
119 size_t frames_in;
120 size_t hw_frame_size;
121 unsigned int requested_rate;
122 unsigned int requested_channels;
123 int read_status;
124 pthread_mutex_t lock;
125 bool standby;
126};
127
128struct j6_stream_out {
129 struct audio_stream_out stream;
130 struct j6_audio_device *dev;
131 struct pcm_config config;
132 struct pcm *pcm;
133 struct timespec last;
134 pthread_mutex_t lock;
135 bool standby;
136 int64_t written; /* total frames written, not cleared when entering standby */
137};
138
139
140static const char *supported_media_cards[] = {
141 "dra7evm",
142 "VayuEVM",
143 "DRA7xxEVM",
144};
145
146static const char *supported_bt_cards[] = {
147 "DRA7xxWiLink",
148};
149
150#define SUPPORTED_IN_DEVICES (AUDIO_DEVICE_IN_BUILTIN_MIC | \
151 AUDIO_DEVICE_IN_WIRED_HEADSET | \
152 AUDIO_DEVICE_IN_DEFAULT)
153#define SUPPORTED_OUT_DEVICES (AUDIO_DEVICE_OUT_SPEAKER | \
154 AUDIO_DEVICE_OUT_WIRED_HEADSET | \
155 AUDIO_DEVICE_OUT_WIRED_HEADPHONE | \
156 AUDIO_DEVICE_OUT_DEFAULT)
157
158#define CAPTURE_SAMPLE_RATE 44100
159#define CAPTURE_PERIOD_SIZE 256
160#define CAPTURE_PERIOD_COUNT 4
161#define CAPTURE_BUFFER_SIZE (CAPTURE_PERIOD_SIZE * CAPTURE_PERIOD_COUNT)
162
163#define PLAYBACK_SAMPLE_RATE 44100
164#define PLAYBACK_PERIOD_SIZE 256
165#define PLAYBACK_PERIOD_COUNT 4
166#define PLAYBACK_BUFFER_SIZE (PLAYBACK_PERIOD_SIZE * PLAYBACK_PERIOD_COUNT)
167
168#define BT_SAMPLE_RATE 8000
169#define BT_PERIOD_SIZE 80
170#define BT_PERIOD_COUNT 4
171#define BT_BUFFER_SIZE (BT_PERIOD_SIZE * BT_PERIOD_COUNT)
172
173struct pcm_config pcm_config_capture = {
174 .channels = 2,
175 .rate = CAPTURE_SAMPLE_RATE,
176 .format = PCM_FORMAT_S16_LE,
177 .period_size = CAPTURE_PERIOD_SIZE,
178 .period_count = CAPTURE_PERIOD_COUNT,
179 .start_threshold = 1,
180 .stop_threshold = CAPTURE_BUFFER_SIZE,
181};
182
183struct pcm_config pcm_config_playback = {
184 .channels = 2,
185 .rate = PLAYBACK_SAMPLE_RATE,
186 .format = PCM_FORMAT_S16_LE,
187 .period_size = PLAYBACK_PERIOD_SIZE,
188 .period_count = PLAYBACK_PERIOD_COUNT,
189 .start_threshold = PLAYBACK_BUFFER_SIZE / 2,
190 .stop_threshold = PLAYBACK_BUFFER_SIZE,
191 .avail_min = PLAYBACK_PERIOD_SIZE,
192};
193
194struct pcm_config pcm_config_bt_in = {
195 .channels = 1,
196 .rate = BT_SAMPLE_RATE,
197 .format = PCM_FORMAT_S16_LE,
198 .period_size = BT_PERIOD_SIZE,
199 .period_count = BT_PERIOD_COUNT,
200};
201
202struct pcm_config pcm_config_bt_out = {
203 .channels = 1,
204 .rate = BT_SAMPLE_RATE,
205 .format = PCM_FORMAT_S16_LE,
206 .period_size = BT_PERIOD_SIZE,
207 .period_count = BT_PERIOD_COUNT,
208};
209
210static void do_out_standby(struct j6_stream_out *out);
211
212/* must be called with device lock held */
213static void select_input_device(struct j6_audio_device *adev)
214{
215 if (adev->in_device & ~SUPPORTED_IN_DEVICES)
216 ALOGW("select_input_device() device not supported, will use default device");
217}
218
219/* must be called with device lock held */
220static void select_output_device(struct j6_audio_device *adev)
221{
222 if (adev->out_device & ~SUPPORTED_OUT_DEVICES)
223 ALOGW("select_output_device() device(s) not supported, will use default devices");
224}
225
226static size_t get_input_buffer_size(uint32_t sample_rate, int format, int channel_count)
227{
228 size_t size;
229
230 /*
231 * take resampling into account and return the closest majoring
232 * multiple of 16 frames, as audioflinger expects audio buffers to
233 * be a multiple of 16 frames
234 */
235 size = (pcm_config_capture.period_size * sample_rate) / pcm_config_capture.rate;
236 size = ((size + 15) / 16) * 16;
237
238 return size * channel_count * audio_bytes_per_sample(format);
239}
240
241/*
242 * Implementation of buffer_remix::remix_func that removes
243 * channels in place without doing any other processing. The
244 * extra channels are truncated.
245 */
246static void remove_channels_from_buf(struct buffer_remix *data, void *buf, size_t frames)
247{
248 size_t samp_size, in_frame, out_frame;
249 size_t N, c;
250 char *s, *d;
251
252 ALOGVV("remove_channels_from_buf() remix=%p buf=%p frames=%u",
253 data, buf, frames);
254
255 if (frames == 0)
256 return;
257
258 samp_size = data->sample_size;
259 in_frame = data->in_chans * samp_size;
260 out_frame = data->out_chans * samp_size;
261
262 if (out_frame >= in_frame) {
263 ALOGE("BUG: remove_channels_from_buf() can not add channels to a buffer.\n");
264 return;
265 }
266
267 N = frames - 1;
268 d = (char*)buf + out_frame;
269 s = (char*)buf + in_frame;
270
271 /* take the first several channels and truncate the rest */
272 while (N--) {
273 for (c = 0; c < out_frame; ++c)
274 d[c] = s[c];
275 d += out_frame;
276 s += in_frame;
277 }
278}
279
280static int setup_stereo_to_mono_input_remix(struct j6_stream_in *in)
281{
282 ALOGV("setup_stereo_to_mono_input_remix() stream=%p", in);
283
284 struct buffer_remix *br = (struct buffer_remix *)calloc(1, sizeof(struct buffer_remix));
285 if (!br)
286 return -ENOMEM;
287
288 br->remix_func = remove_channels_from_buf;
289 br->sample_size = sizeof(int16_t);
290 br->in_chans = 2;
291 br->out_chans = 1;
292 in->remix = br;
293
294 return 0;
295}
296
297/*
298 * Implementation of buffer_remix::remix_func that duplicates the first
299 * channel into the rest of channels in the frame without doing any other
300 * processing
301 */
302static void duplicate_channels_from_mono(struct buffer_remix *data, void *buf, size_t frames)
303{
304 int samp_size, in_frame, out_frame;
305 int N, c;
306 char *s, *d;
307
308 ALOGVV("duplicate_channels_from_mono() remix=%p buf=%p frames=%u",
309 data, buf, frames);
310
311 if (frames == 0)
312 return;
313
314 samp_size = data->sample_size;
315 in_frame = data->in_chans * samp_size;
316 out_frame = data->out_chans * samp_size;
317
318 if (in_frame >= out_frame) {
319 ALOGE("BUG: duplicate_channels_from_mono() can not drop channels\n");
320 return;
321 }
322
323 N = frames - 1;
324 d = (char*)buf + N * out_frame;
325 s = (char*)buf + N * in_frame;
326
327 /* duplicate first channel into the rest of channels in the frame */
328 while (N-- >= 0) {
329 for (c = 0; c < out_frame; ++c)
330 d[c] = s[c % in_frame];
331 d -= out_frame;
332 s -= in_frame;
333 }
334}
335
336static int setup_voice_remix(struct j6_voice_stream *stream)
337{
338 ALOGVV("setup_voice_mono_to_stereo_input_remix() %s stream", stream->name);
339
340 struct buffer_remix *br = (struct buffer_remix *)calloc(1, sizeof(struct buffer_remix));
341 if (!br)
342 return -ENOMEM;
343
344 br->remix_func = duplicate_channels_from_mono;
345 br->sample_size = sizeof(int16_t);
346 br->in_chans = stream->in_config.channels;
347 br->out_chans = stream->out_config.channels;
348
349 if (br->in_chans == 1)
350 br->remix_func = duplicate_channels_from_mono;
351 else if (br->out_chans == 1)
352 br->remix_func = remove_channels_from_buf;
353 else
354 return -ENOTSUP;
355
356 stream->remix = br;
357
358 return 0;
359}
360
361static int voice_get_next_buffer(struct resampler_buffer_provider *buffer_provider,
362 struct resampler_buffer* buffer)
363{
364 struct j6_voice_stream *stream;
365 int ret;
366
367 if (buffer_provider == NULL || buffer == NULL) {
368 ALOGE("voice_get_next_buffer() invalid buffer/provider");
369 return -EINVAL;
370 }
371
372 stream = (struct j6_voice_stream *)((char *)buffer_provider -
373 offsetof(struct j6_voice_stream, buf_provider));
374
375 if (stream->pcm_in == NULL) {
376 buffer->raw = NULL;
377 buffer->frame_count = 0;
378 return -ENODEV;
379 }
380
381 if (buffer->frame_count > stream->in_frames) {
382 ALOGW("voice_get_next_buffer() %s unexpected frame count %u, "
383 "buffer was allocated for %u frames",
384 stream->name, buffer->frame_count, stream->in_frames);
385 buffer->frame_count = stream->in_frames;
386 }
387
388 ret = pcm_read(stream->pcm_in, stream->in_buffer,
389 buffer->frame_count * stream->in_frame_size);
390 if (ret) {
391 ALOGE("voice_get_next_buffer() failed to read %s: %s",
392 stream->name, pcm_get_error(stream->pcm_in));
393 buffer->raw = NULL;
394 buffer->frame_count = 0;
395 return ret;
396 }
397
398 buffer->i16 = stream->in_buffer;
399
400 return ret;
401}
402
403static void voice_release_buffer(struct resampler_buffer_provider *buffer_provider,
404 struct resampler_buffer* buffer)
405{
406 UNUSED(buffer_provider);
407 UNUSED(buffer);
408}
409
410static void *voice_thread_func(void *arg)
411{
412 struct j6_voice_stream *stream = (struct j6_voice_stream *)arg;
413 struct j6_audio_device *adev = stream->dev;
414 size_t frames = stream->out_frames;
415 uint32_t periods = 0;
416 uint32_t avail;
417 bool in_steady = false;
418 bool out_steady = false;
419 int ret = 0;
420
421 pcm_start(stream->pcm_in);
422
423 memset(stream->out_buffer, 0, stream->out_frames * stream->out_frame_size);
424
425 while (adev->in_call) {
426 if (out_steady) {
427 if (in_steady) {
428 stream->resampler->resample_from_provider(stream->resampler,
429 stream->out_buffer,
430 &frames);
431 } else {
432 avail = pcm_avail_update(stream->pcm_in);
433 if (avail > 0) {
434 in_steady = true;
435 continue;
436 }
437 }
438 } else if (++periods == stream->out_config.period_count) {
439 out_steady = true;
440 }
441
442 if (stream->remix)
443 stream->remix->remix_func(stream->remix, stream->out_buffer, frames);
444
445 ret = pcm_write(stream->pcm_out, stream->out_buffer,
446 frames * stream->out_frame_size);
447 if (ret) {
448 ALOGE("voice_thread_func() failed to write %s: %s",
449 stream->name, pcm_get_error(stream->pcm_out));
450 usleep((frames * 1000000) / stream->out_config.rate);
451 }
452 }
453
454 return (void*)ret;
455}
456
457static void voice_stream_exit(struct j6_voice_stream *stream)
458{
459 if (stream->resampler) {
460 release_resampler(stream->resampler);
461 stream->resampler = NULL;
462 }
463
464 if (stream->pcm_out) {
465 pcm_close(stream->pcm_out);
466 stream->pcm_out = NULL;
467 }
468
469 if (stream->pcm_in) {
470 pcm_close(stream->pcm_in);
471 stream->pcm_in = NULL;
472 }
473
474 if (stream->in_buffer) {
475 free(stream->in_buffer);
476 stream->in_buffer = NULL;
477 stream->in_frames = 0;
478 }
479
480 if (stream->out_buffer) {
481 free(stream->out_buffer);
482 stream->out_buffer = NULL;
483 stream->out_frames = 0;
484 }
485
486 if (stream->remix) {
487 free(stream->remix);
488 stream->remix = NULL;
489 }
490
491 if (stream->name) {
492 free(stream->name);
493 stream->name = NULL;
494 }
495}
496
497static int voice_stream_init(struct j6_voice_stream *stream,
498 unsigned int in_card,
499 unsigned int in_port,
500 unsigned int out_card,
501 unsigned int out_port)
502{
503 struct j6_audio_device *adev = stream->dev;
504 int frames;
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 stream->in_config.channels,
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(in_card, in_port,
521 PCM_IN | PCM_MONOTONIC,
522 &stream->in_config);
523 stream->pcm_out = pcm_open(out_card, out_port,
524 PCM_OUT | PCM_MONOTONIC,
525 &stream->out_config);
526
527 if (!pcm_is_ready(stream->pcm_in) || !pcm_is_ready(stream->pcm_out)) {
528 ALOGE("voice_stream_init() failed to open pcm %s devices", stream->name);
529 voice_stream_exit(stream);
530 return -ENODEV;
531 }
532
533 /*
534 * Choose the largest frame size since mono-to-stereo and
535 * stereo-to-mono conversion happens in place
536 */
537 stream->in_frame_size = pcm_frames_to_bytes(stream->pcm_in, 1);
538 stream->out_frame_size = pcm_frames_to_bytes(stream->pcm_out, 1);
539 frames = (stream->in_frame_size > stream->out_frame_size) ?
540 stream->in_frame_size : stream->out_frame_size;
541
542 /* out_buffer will store the resampled data */
543 stream->out_frames = stream->out_config.period_size;
544 stream->out_buffer = malloc(stream->out_frames * frames);
545
546 /* in_buffer will store the frames recorded from the PCM device */
547 stream->in_frames = (stream->out_frames * stream->in_config.rate) / stream->out_config.rate +
548 RESAMPLER_HEADROOM_FRAMES;
549 stream->in_buffer = malloc(stream->in_frames * frames);
550
551 if (!stream->in_buffer || !stream->out_buffer) {
552 ALOGE("voice_stream_init() failed to allocate %s buffers", stream->name);
553 voice_stream_exit(stream);
554 return -ENOMEM;
555 }
556
557 ret = setup_voice_remix(stream);
558 if (ret) {
559 ALOGE("voice_stream_init() failed to setup remix %d", ret);
560 voice_stream_exit(stream);
561 }
562
563 return ret;
564}
565
566static int enter_voice_call(struct j6_audio_device *adev)
567{
568 struct j6_voice *voice = &adev->voice;
569 int ret;
570
571 ALOGI("enter_voice_call() entering bluetooth voice call");
572
573 /* Let the primary output switch to a dummy sink */
574 if (adev->out)
575 do_out_standby(adev->out);
576
577 /* Uplink: Mic (44.1kHz) -> BT (8kHz) */
578 voice->ul.name = strdup("UL");
579 voice->ul.in_config = pcm_config_capture;
580 voice->ul.out_config = pcm_config_bt_out;
581 voice->ul.dev = adev;
582 ret = voice_stream_init(&voice->ul, adev->card, adev->in_port,
583 adev->bt_card, adev->bt_port);
584 if (ret) {
585 ALOGE("enter_voice_call() failed to init uplink %d", ret);
586 return ret;
587 }
588
589 /* Downlink: BT (8kHz) -> HP/Spk (44.1kHz) */
590 voice->dl.name = strdup("DL");
591 voice->dl.in_config = pcm_config_bt_in;
592 voice->dl.out_config = pcm_config_playback;
593 voice->dl.dev = adev;
594 ret = voice_stream_init(&voice->dl, adev->bt_card, adev->bt_port,
595 adev->card, adev->out_port);
596 if (ret) {
597 ALOGE("enter_voice_call() failed to init downlink %d", ret);
598 goto err_dl_init;
599 }
600
601 adev->in_call = true;
602
603 /* Create uplink thread: Mic -> BT */
604 ret = pthread_create(&voice->ul.thread, NULL, voice_thread_func, &voice->ul);
605 if (ret) {
606 ALOGE("enter_voice_call() failed to create uplink thread %d", ret);
607 adev->in_call = false;
608 goto err_ul_thread;
609 }
610
611 /* Create downlink thread: BT -> HP/Spk */
612 ret = pthread_create(&voice->dl.thread, NULL, voice_thread_func, &voice->dl);
613 if (ret) {
614 ALOGE("enter_voice_call() failed to create downlink thread %d", ret);
615 adev->in_call = false;
616 goto err_dl_thread;
617 }
618
619 return 0;
620
621 err_dl_thread:
622 pthread_join(voice->ul.thread, NULL);
623 err_ul_thread:
624 voice_stream_exit(&voice->ul);
625 err_dl_init:
626 voice_stream_exit(&voice->dl);
627
628 return ret;
629}
630
631static void leave_voice_call(struct j6_audio_device *adev)
632{
633 struct j6_voice *voice = &adev->voice;
634 struct j6_voice_stream *ul = &voice->ul;
635 struct j6_voice_stream *dl = &voice->dl;
636 void *ret;
637
638 ALOGI("leave_voice_call() leaving bluetooth voice call");
639
640 adev->in_call = false;
641
642 if (ul->pcm_out)
643 pcm_stop(ul->pcm_out);
644 if (dl->pcm_in)
645 pcm_stop(dl->pcm_in);
646
647 pthread_join(voice->dl.thread, &ret);
648 pthread_join(voice->ul.thread, &ret);
649
650 voice_stream_exit(&voice->dl);
651 voice_stream_exit(&voice->ul);
652
653 /* Let the primary output switch back to its ALSA PCM device */
654 if (adev->out)
655 do_out_standby(adev->out);
656}
657
658static uint32_t time_diff(struct timespec t1, struct timespec t0)
659{
660 struct timespec temp;
661
662 if ((t1.tv_nsec - t0.tv_nsec) < 0) {
663 temp.tv_sec = t1.tv_sec - t0.tv_sec-1;
664 temp.tv_nsec = 1000000000UL + t1.tv_nsec - t0.tv_nsec;
665 } else {
666 temp.tv_sec = t1.tv_sec - t0.tv_sec;
667 temp.tv_nsec = t1.tv_nsec - t0.tv_nsec;
668 }
669
670 return (temp.tv_sec * 1000000UL + temp.tv_nsec / 1000);
671}
672
673/* audio HAL functions */
674
675static uint32_t out_get_sample_rate(const struct audio_stream *stream)
676{
677 uint32_t rate = PLAYBACK_SAMPLE_RATE;
678
679 UNUSED(stream);
680 ALOGVV("out_get_sample_rate() stream=%p rate=%u", stream, rate);
681
682 return rate;
683}
684
685static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
686{
687 UNUSED(stream);
688 UNUSED(rate);
689 ALOGVV("out_set_sample_rate() stream=%p rate=%u", stream, rate);
690
691 return 0;
692}
693
694static size_t out_get_buffer_size(const struct audio_stream *stream)
695{
696 const struct audio_stream_out *s = (const struct audio_stream_out *)stream;
697 uint32_t frames = ((PLAYBACK_PERIOD_SIZE + 15) / 16) * 16;
698 size_t bytes = frames * audio_stream_out_frame_size(s);
699
700 ALOGVV("out_get_buffer_size() stream=%p frames=%u bytes=%u", stream, frames, bytes);
701
702 return bytes;
703}
704
705static audio_channel_mask_t out_get_channels(const struct audio_stream *stream)
706{
707 audio_channel_mask_t channels = AUDIO_CHANNEL_OUT_STEREO;
708
709 UNUSED(stream);
710 ALOGVV("out_get_channels() stream=%p channels=%u", stream, popcount(channels));
711
712 return channels;
713}
714
715static audio_format_t out_get_format(const struct audio_stream *stream)
716{
717 audio_format_t format = AUDIO_FORMAT_PCM_16_BIT;
718
719 UNUSED(stream);
720 ALOGVV("out_set_format() stream=%p format=0x%08x (%u bits/sample)",
721 stream, format, audio_bytes_per_sample(format) << 3);
722
723 return format;
724}
725
726static int out_set_format(struct audio_stream *stream, audio_format_t format)
727{
728 UNUSED(stream);
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 UNUSED(stream);
774 UNUSED(fd);
775
776 return 0;
777}
778
779static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
780{
781 struct j6_stream_out *out = (struct j6_stream_out *)(stream);
782 struct j6_audio_device *adev = out->dev;
783 struct str_parms *parms;
784 char value[32];
785 int ret;
786 uint32_t val = 0;
787
788 ALOGV("out_set_parameters() stream=%p parameter='%s'", out, kvpairs);
789
790 parms = str_parms_create_str(kvpairs);
791
792 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
793 if (ret >= 0) {
794 val = atoi(value);
795 pthread_mutex_lock(&adev->lock);
796 pthread_mutex_lock(&out->lock);
797 if (val != 0) {
798 if ((adev->out_device & AUDIO_DEVICE_OUT_ALL) != val)
799 do_out_standby(out);
800
801 /* set the active output device */
802 adev->out_device = val;
803 select_output_device(adev);
804 }
805 pthread_mutex_unlock(&out->lock);
806 pthread_mutex_unlock(&adev->lock);
807 }
808
809 return 0;
810}
811
812static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
813{
814 UNUSED(stream);
815 UNUSED(keys);
816
817 return strdup("");
818}
819
820static uint32_t out_get_latency(const struct audio_stream_out *stream)
821{
822 const struct j6_stream_out *out = (const struct j6_stream_out *)(stream);
823 uint32_t frames = PLAYBACK_BUFFER_SIZE;
824 uint32_t latency = (frames * 1000) / PLAYBACK_SAMPLE_RATE;
825
826 ALOGVV("out_get_latency() stream=%p latency=%u msecs", out, latency);
827
828 return latency;
829}
830
831static int out_set_volume(struct audio_stream_out *stream, float left,
832 float right)
833{
834 UNUSED(stream);
835 UNUSED(left);
836 UNUSED(right);
837
838 return -ENOSYS;
839}
840
841static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
842 size_t bytes)
843{
844 const struct audio_stream_out *s = (const struct audio_stream_out *)stream;
845 struct j6_stream_out *out = (struct j6_stream_out *)(stream);
846 struct j6_audio_device *adev = out->dev;
847 struct timespec now;
848 const size_t frame_size = audio_stream_out_frame_size(s);
849 const size_t frames = bytes / frame_size;
850 uint32_t rate = out->config.rate;
851 uint32_t write_usecs = frames * 1000000 / rate;
852 uint32_t diff_usecs;
853 int ret = 0;
854
855 ALOGVV("out_write() stream=%p buffer=%p size=%u/%u time=%u usecs",
856 out, buffer, frames, rate, write_usecs);
857
858 pthread_mutex_lock(&adev->lock);
859 pthread_mutex_lock(&out->lock);
860
861 if (out->standby) {
862 if (!adev->in_call) {
863 select_output_device(adev);
864
865 ALOGI("out_write() open card %u port %u", adev->card, adev->out_port);
866 out->pcm = pcm_open(adev->card, adev->out_port,
867 PCM_OUT | PCM_MONOTONIC,
868 &out->config);
869 if (!pcm_is_ready(out->pcm)) {
870 ALOGE("out_write() failed to open pcm out: %s", pcm_get_error(out->pcm));
871 pcm_close(out->pcm);
872 out->pcm = NULL;
873 ret = -ENODEV;
874 }
875 } else {
876 ALOGI("out_write() open dummy port");
877 clock_gettime(CLOCK_REALTIME, &out->last);
878 }
879
880 if (ret) {
881 usleep(write_usecs); /* limits the rate of error messages */
882 pthread_mutex_unlock(&out->lock);
883 pthread_mutex_unlock(&adev->lock);
884 return ret;
885 }
886
887 out->standby = false;
888 }
889
890 pthread_mutex_unlock(&adev->lock);
891
892 if (!adev->in_call) {
893 ret = pcm_write(out->pcm, buffer, bytes);
894 if (ret) {
895 ALOGE("out_write() failed to write audio data %d", ret);
896 usleep(write_usecs); /* limits the rate of error messages */
897 }
898 } else {
899 clock_gettime(CLOCK_REALTIME, &now);
900 diff_usecs = time_diff(now, out->last);
901 if (write_usecs > diff_usecs)
902 usleep(write_usecs - diff_usecs);
903
904 clock_gettime(CLOCK_REALTIME, &out->last);
905 }
906
907 out->written += frames;
908
909 pthread_mutex_unlock(&out->lock);
910
911 return bytes;
912}
913
914static int out_get_render_position(const struct audio_stream_out *stream,
915 uint32_t *dsp_frames)
916{
917 UNUSED(stream);
918 UNUSED(dsp_frames);
919
920 return -EINVAL;
921}
922
923static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
924{
925 UNUSED(stream);
926 UNUSED(effect);
927
928 return 0;
929}
930
931static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
932{
933 UNUSED(stream);
934 UNUSED(effect);
935
936 return 0;
937}
938
939static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
940 int64_t *timestamp)
941{
942 UNUSED(stream);
943 UNUSED(timestamp);
944
945 return -EINVAL;
946}
947
948static int out_get_presentation_position(const struct audio_stream_out *stream,
949 uint64_t *frames, struct timespec *timestamp)
950{
951 struct j6_stream_out *out = (struct j6_stream_out *)(stream);
952 struct j6_audio_device *adev = out->dev;
953 int64_t signed_frames = -1;
954 size_t avail;
955 int ret = -1;
956
957 pthread_mutex_lock(&out->lock);
958
959 if (!adev->in_call) {
960 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
961 signed_frames = out->written - pcm_get_buffer_size(out->pcm) + avail;
962 }
963 } else {
964 clock_gettime(CLOCK_MONOTONIC, timestamp);
965 signed_frames = out->written +
966 (time_diff(*timestamp, out->last) * out->config.rate) / 1000000;
967 }
968
969 /* It would be unusual for this value to be negative, but check just in case ... */
970 if (signed_frames >= 0) {
971 *frames = signed_frames;
972 ret = 0;
973 }
974
975 pthread_mutex_unlock(&out->lock);
976
977 return ret;
978}
979
980/** audio_stream_in implementation **/
981static uint32_t in_get_sample_rate(const struct audio_stream *stream)
982{
983 const struct j6_stream_in *in = (const struct j6_stream_in *)(stream);
984
985 ALOGVV("in_get_sample_rate() stream=%p rate=%u", stream, in->requested_rate);
986
987 return in->requested_rate;
988}
989
990static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
991{
992 ALOGV("in_set_sample_rate() stream=%p rate=%u", stream, rate);
993
994 return 0;
995}
996
997static size_t in_get_buffer_size(const struct audio_stream *stream)
998{
999 const struct j6_stream_in *in = (const struct j6_stream_in *)(stream);
1000
1001 size_t bytes = get_input_buffer_size(in->requested_rate,
1002 AUDIO_FORMAT_PCM_16_BIT,
1003 in->requested_channels);
1004
1005 ALOGVV("in_get_buffer_size() stream=%p bytes=%u", in, bytes);
1006
1007 return bytes;
1008}
1009
1010static audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
1011{
1012 const struct j6_stream_in *in = (const struct j6_stream_in *)(stream);
1013 audio_channel_mask_t channels = audio_channel_in_mask_from_count(in->requested_channels);
1014
1015 ALOGVV("in_get_channels() stream=%p channels=%u", in, in->requested_channels);
1016
1017 return channels;
1018}
1019
1020static audio_format_t in_get_format(const struct audio_stream *stream)
1021{
1022 audio_format_t format = AUDIO_FORMAT_PCM_16_BIT;
1023
1024 UNUSED(stream);
1025 ALOGVV("in_set_format() stream=%p format=0x%08x (%u bits/sample)",
1026 stream, format, audio_bytes_per_sample(format) << 3);
1027
1028 return format;
1029}
1030
1031static int in_set_format(struct audio_stream *stream, audio_format_t format)
1032{
1033 UNUSED(stream);
1034 ALOGV("in_set_format() stream=%p format=0x%08x (%u bits/sample)",
1035 stream, format, audio_bytes_per_sample(format) << 3);
1036
1037 if (format != AUDIO_FORMAT_PCM_16_BIT) {
1038 return -ENOSYS;
1039 } else {
1040 return 0;
1041 }
1042}
1043
1044/* must be called with locks held */
1045static void do_in_standby(struct j6_stream_in *in)
1046{
1047 struct j6_audio_device *adev = in->dev;
1048
1049 if (!in->standby) {
1050 ALOGI("do_in_standby() close card %u port %u", adev->card, adev->out_port);
1051 pcm_close(in->pcm);
1052 in->pcm = NULL;
1053 in->standby = true;
1054 }
1055}
1056
1057static int in_standby(struct audio_stream *stream)
1058{
1059 struct j6_stream_in *in = (struct j6_stream_in *)(stream);
1060 struct j6_audio_device *adev = in->dev;
1061
1062 ALOGV("in_standby() stream=%p", in);
1063 pthread_mutex_lock(&adev->lock);
1064 pthread_mutex_lock(&in->lock);
1065 do_in_standby(in);
1066 pthread_mutex_unlock(&in->lock);
1067 pthread_mutex_unlock(&adev->lock);
1068
1069 return 0;
1070}
1071
1072static int in_dump(const struct audio_stream *stream, int fd)
1073{
1074 UNUSED(stream);
1075 UNUSED(fd);
1076
1077 return 0;
1078}
1079
1080static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
1081{
1082 struct j6_stream_in *in = (struct j6_stream_in *)(stream);
1083 struct j6_audio_device *adev = in->dev;
1084 struct str_parms *parms;
1085 char value[32];
1086 int ret;
1087 uint32_t val = 0;
1088
1089 ALOGV("in_set_parameters() stream=%p parameter='%s'", stream, kvpairs);
1090
1091 parms = str_parms_create_str(kvpairs);
1092
1093 /* Nothing to do for AUDIO_PARAMETER_STREAM_INPUT_SOURCE, so it's ignored */
1094
1095 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1096 if (ret >= 0) {
1097 val = atoi(value);
1098 pthread_mutex_lock(&adev->lock);
1099 pthread_mutex_lock(&in->lock);
1100 if (val != 0) {
1101 if ((adev->in_device & AUDIO_DEVICE_IN_ALL) != val)
1102 do_in_standby(in);
1103
1104 /* set the active input device */
1105 adev->in_device = val;
1106 select_input_device(adev);
1107 }
1108 pthread_mutex_unlock(&in->lock);
1109 pthread_mutex_unlock(&adev->lock);
1110 }
1111
1112 return 0;
1113}
1114
1115static char * in_get_parameters(const struct audio_stream *stream,
1116 const char *keys)
1117{
1118 UNUSED(stream);
1119 UNUSED(keys);
1120
1121 return strdup("");
1122}
1123
1124static int in_set_gain(struct audio_stream_in *stream, float gain)
1125{
1126 UNUSED(stream);
1127 UNUSED(gain);
1128
1129 return 0;
1130}
1131
1132static int get_next_buffer(struct resampler_buffer_provider *buffer_provider,
1133 struct resampler_buffer* buffer)
1134{
1135 struct j6_stream_in *in;
1136 struct buffer_remix *remix;
1137
1138 if (buffer_provider == NULL || buffer == NULL)
1139 return -EINVAL;
1140
1141 in = (struct j6_stream_in *)((char *)buffer_provider -
1142 offsetof(struct j6_stream_in, buf_provider));
1143
1144 if (in->pcm == NULL) {
1145 buffer->raw = NULL;
1146 buffer->frame_count = 0;
1147 in->read_status = -ENODEV;
1148 return -ENODEV;
1149 }
1150
1151 if (in->frames_in == 0) {
1152 in->read_status = pcm_read(in->pcm,
1153 (void*)in->buffer,
1154 buffer->frame_count * in->hw_frame_size);
1155 if (in->read_status != 0) {
1156 ALOGE("get_next_buffer() pcm_read error %d", in->read_status);
1157 buffer->raw = NULL;
1158 buffer->frame_count = 0;
1159 return in->read_status;
1160 }
1161 in->frames_in = buffer->frame_count;
1162
1163 remix = in->remix;
1164 if (remix)
1165 remix->remix_func(remix, in->buffer, in->frames_in);
1166 }
1167
1168 buffer->frame_count = (buffer->frame_count > in->frames_in) ?
1169 in->frames_in : buffer->frame_count;
1170 buffer->i16 = in->buffer;
1171
1172 return in->read_status;
1173}
1174
1175static void release_buffer(struct resampler_buffer_provider *buffer_provider,
1176 struct resampler_buffer* buffer)
1177{
1178 struct j6_stream_in *in;
1179
1180 if (buffer_provider == NULL || buffer == NULL)
1181 return;
1182
1183 in = (struct j6_stream_in *)((char *)buffer_provider -
1184 offsetof(struct j6_stream_in, buf_provider));
1185
1186 in->frames_in -= buffer->frame_count;
1187}
1188
1189/*
1190 * read_frames() reads frames from kernel driver, down samples to capture rate
1191 * if necessary and output the number of frames requested to the buffer specified
1192 */
1193static ssize_t read_frames(struct j6_stream_in *in, void *buffer, ssize_t frames)
1194{
1195 const struct audio_stream_in *s = (const struct audio_stream_in *)in;
1196 ssize_t frames_wr = 0;
1197 size_t frame_size;
1198
1199 ALOGVV("read_frames() stream=%p frames=%u", in, frames);
1200
1201 if (in->remix)
1202 frame_size = audio_stream_in_frame_size(s);
1203 else
1204 frame_size = in->hw_frame_size;
1205
1206 while (frames_wr < frames) {
1207 size_t frames_rd = frames - frames_wr;
1208
1209 if (in->resampler) {
1210 in->resampler->resample_from_provider(in->resampler,
1211 (int16_t *)((char *)buffer + frames_wr * frame_size),
1212 &frames_rd);
1213 } else {
1214 struct resampler_buffer buf = {
1215 { raw : NULL, },
1216 frame_count : frames_rd,
1217 };
1218 get_next_buffer(&in->buf_provider, &buf);
1219 if (buf.raw) {
1220 memcpy((char *)buffer + frames_wr * frame_size,
1221 buf.raw,
1222 buf.frame_count * frame_size);
1223 frames_rd = buf.frame_count;
1224 }
1225 release_buffer(&in->buf_provider, &buf);
1226 }
1227
1228 /* in->read_status is updated by getNextBuffer() also called by
1229 * in->resampler->resample_from_provider() */
1230 if (in->read_status != 0)
1231 return in->read_status;
1232
1233 frames_wr += frames_rd;
1234 }
1235
1236 return frames_wr;
1237}
1238
1239static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
1240 size_t bytes)
1241{
1242 const struct audio_stream_in *s = (const struct audio_stream_in *)stream;
1243 struct j6_stream_in *in = (struct j6_stream_in *)(stream);
1244 struct j6_audio_device *adev = in->dev;
1245 const size_t frame_size = audio_stream_in_frame_size(stream);
1246 const size_t frames = bytes / frame_size;
1247 uint32_t rate = in_get_sample_rate(&stream->common);
1248 uint32_t read_usecs = frames * 1000000 / rate;
1249 int ret;
1250
1251 ALOGVV("in_read() stream=%p buffer=%p size=%u/%u time=%u usecs",
1252 stream, buffer, frames, rate, read_usecs);
1253
1254 pthread_mutex_lock(&adev->lock);
1255 pthread_mutex_lock(&in->lock);
1256
1257 if (in->standby) {
1258 select_input_device(adev);
1259
1260 ALOGI("in_read() open card %u port %u", adev->card, adev->in_port);
1261 in->pcm = pcm_open(adev->card, adev->in_port,
1262 PCM_IN | PCM_MONOTONIC,
1263 &in->config);
1264 if (!pcm_is_ready(in->pcm)) {
1265 ALOGE("in_read() failed to open pcm in: %s", pcm_get_error(in->pcm));
1266 pcm_close(in->pcm);
1267 in->pcm = NULL;
1268 usleep(read_usecs); /* limits the rate of error messages */
1269 pthread_mutex_unlock(&in->lock);
1270 pthread_mutex_unlock(&adev->lock);
1271 return -ENODEV;
1272 }
1273
1274 /* if no supported sample rate is available, use the resampler */
1275 if (in->resampler) {
1276 in->resampler->reset(in->resampler);
1277 in->frames_in = 0;
1278 }
1279
1280 in->standby = false;
1281 }
1282
1283 pthread_mutex_unlock(&adev->lock);
1284
1285 if (in->resampler || in->remix)
1286 ret = read_frames(in, buffer, frames);
1287 else
1288 ret = pcm_read(in->pcm, buffer, bytes);
1289
1290 if (ret < 0) {
1291 ALOGE("in_read() failed to read audio data %d", ret);
1292 usleep(read_usecs); /* limits the rate of error messages */
1293 memset(buffer, 0, bytes);
1294 } else if (adev->mic_mute) {
1295 memset(buffer, 0, bytes);
1296 }
1297
1298 pthread_mutex_unlock(&in->lock);
1299
1300 return bytes;
1301}
1302
1303static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
1304{
1305 UNUSED(stream);
1306 ALOGVV("in_get_input_frames_lost() stream=%p frames=%u", stream, 0);
1307
1308 return 0;
1309}
1310
1311static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1312{
1313 UNUSED(stream);
1314 UNUSED(effect);
1315
1316 return 0;
1317}
1318
1319static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1320{
1321 UNUSED(stream);
1322 UNUSED(effect);
1323
1324 return 0;
1325}
1326
1327static int adev_open_output_stream(struct audio_hw_device *dev,
1328 audio_io_handle_t handle,
1329 audio_devices_t devices,
1330 audio_output_flags_t flags,
1331 struct audio_config *config,
1332 struct audio_stream_out **stream_out,
1333 const char *address)
1334{
1335 struct j6_audio_device *adev = (struct j6_audio_device *)dev;
1336 struct j6_stream_out *out;
1337
1338 UNUSED(handle);
1339 UNUSED(devices);
1340 UNUSED(address);
1341
1342 out = (struct j6_stream_out *)calloc(1, sizeof(struct j6_stream_out));
1343 if (!out)
1344 return -ENOMEM;
1345
1346 ALOGV("adev_open_output_stream() stream=%p rate=%u channels=%u "
1347 "format=0x%08x flags=0x%08x",
1348 out, config->sample_rate, popcount(config->channel_mask),
1349 config->format, flags);
1350
1351 pthread_mutex_init(&out->lock, NULL);
1352
1353 out->stream.common.get_sample_rate = out_get_sample_rate;
1354 out->stream.common.set_sample_rate = out_set_sample_rate;
1355 out->stream.common.get_buffer_size = out_get_buffer_size;
1356 out->stream.common.get_channels = out_get_channels;
1357 out->stream.common.get_format = out_get_format;
1358 out->stream.common.set_format = out_set_format;
1359 out->stream.common.standby = out_standby;
1360 out->stream.common.dump = out_dump;
1361 out->stream.common.set_parameters = out_set_parameters;
1362 out->stream.common.get_parameters = out_get_parameters;
1363 out->stream.common.add_audio_effect = out_add_audio_effect;
1364 out->stream.common.remove_audio_effect = out_remove_audio_effect;
1365 out->stream.get_latency = out_get_latency;
1366 out->stream.set_volume = out_set_volume;
1367 out->stream.write = out_write;
1368 out->stream.get_render_position = out_get_render_position;
1369 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
1370 out->stream.get_presentation_position = out_get_presentation_position;
1371
1372 out->dev = adev;
1373 out->standby = true;
1374 out->config = pcm_config_playback;
1375 out->written = 0;
1376 adev->out = out;
1377
1378 config->format = out_get_format(&out->stream.common);
1379 config->channel_mask = out_get_channels(&out->stream.common);
1380 config->sample_rate = out_get_sample_rate(&out->stream.common);
1381
1382 *stream_out = &out->stream;
1383
1384 return 0;
1385}
1386
1387static void adev_close_output_stream(struct audio_hw_device *dev,
1388 struct audio_stream_out *stream)
1389{
1390 struct j6_audio_device *adev = (struct j6_audio_device *)dev;
1391 struct j6_stream_out *out = (struct j6_stream_out *)(stream);
1392
1393 ALOGV("adev_close_output_stream() stream=%p", out);
1394
1395 out_standby(&stream->common);
1396 out->dev = NULL;
1397 adev->out = NULL;
1398
1399 free(stream);
1400}
1401
1402static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
1403{
1404 UNUSED(dev);
1405 UNUSED(kvpairs);
1406
1407 return -ENOSYS;
1408}
1409
1410static char * adev_get_parameters(const struct audio_hw_device *dev,
1411 const char *keys)
1412{
1413 UNUSED(dev);
1414 UNUSED(keys);
1415
1416 return strdup("");;
1417}
1418
1419static int adev_init_check(const struct audio_hw_device *dev)
1420{
1421 UNUSED(dev);
1422
1423 return 0;
1424}
1425
1426static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
1427{
1428 UNUSED(dev);
1429 UNUSED(volume);
1430
1431 return -ENOSYS;
1432}
1433
1434static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
1435{
1436 UNUSED(dev);
1437 UNUSED(volume);
1438
1439 return -ENOSYS;
1440}
1441
1442static int adev_get_master_volume(struct audio_hw_device *dev, float *volume)
1443{
1444 UNUSED(dev);
1445 UNUSED(volume);
1446
1447 return -ENOSYS;
1448}
1449
1450static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
1451{
1452 UNUSED(dev);
1453 UNUSED(muted);
1454
1455 return -ENOSYS;
1456}
1457
1458static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
1459{
1460 UNUSED(dev);
1461 UNUSED(muted);
1462
1463 return -ENOSYS;
1464}
1465
1466static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
1467{
1468 struct j6_audio_device *adev = (struct j6_audio_device *)dev;
1469 struct j6_stream_out *out = adev->out;
1470 int ret = 0;
1471
1472 ALOGV("adev_set_mode() mode=0x%08x", mode);
1473
1474 pthread_mutex_lock(&adev->lock);
1475 pthread_mutex_lock(&out->lock);
1476
1477 if (adev->mode == mode) {
1478 ALOGV("adev_set_mode() already in mode=0x%08x", mode);
1479 goto out;
1480 }
1481
1482 if (mode == AUDIO_MODE_IN_CALL) {
1483 ret = enter_voice_call(adev);
1484 if (ret) {
1485 ALOGE("adev_set_mode() failed to initialize voice call %d", ret);
1486 goto out;
1487 }
1488 } else if (adev->mode == AUDIO_MODE_IN_CALL) {
1489 leave_voice_call(adev);
1490 }
1491
1492 adev->mode = mode;
1493
1494out:
1495 pthread_mutex_unlock(&out->lock);
1496 pthread_mutex_unlock(&adev->lock);
1497
1498 return ret;
1499}
1500
1501static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
1502{
1503 struct j6_audio_device *adev = (struct j6_audio_device *)dev;
1504
1505 ALOGV("adev_set_mic_mute() state=%s", state ? "mute" : "unmute");
1506 adev->mic_mute = state;
1507
1508 return 0;
1509}
1510
1511static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
1512{
1513 const struct j6_audio_device *adev = (const struct j6_audio_device *)dev;
1514
1515 *state = adev->mic_mute;
1516 ALOGV("adev_get_mic_mute() state=%s", *state ? "mute" : "unmute");
1517
1518 return 0;
1519}
1520
1521static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
1522 const struct audio_config *config)
1523{
1524 UNUSED(dev);
1525
1526 size_t bytes = get_input_buffer_size(config->sample_rate,
1527 config->format,
1528 popcount(config->channel_mask));
1529
1530 ALOGVV("adev_in_get_buffer_size() bytes=%u", bytes);
1531
1532 return bytes;
1533}
1534
1535static int adev_open_input_stream(struct audio_hw_device *dev,
1536 audio_io_handle_t handle,
1537 audio_devices_t devices,
1538 struct audio_config *config,
1539 struct audio_stream_in **stream_in,
1540 audio_input_flags_t flags,
1541 const char *address,
1542 audio_source_t source)
1543{
1544 struct j6_audio_device *adev = (struct j6_audio_device *)dev;
1545 struct j6_stream_in *in;
1546 int buffer_size;
1547 int ret;
1548
1549 UNUSED(handle);
1550 UNUSED(devices);
1551 UNUSED(flags);
1552 UNUSED(address);
1553 UNUSED(source);
1554
1555 in = (struct j6_stream_in *)calloc(1, sizeof(struct j6_stream_in));
1556 if (!in)
1557 return -ENOMEM;
1558
1559 ALOGV("adev_open_input_stream() stream=%p rate=%u channels=%u format=0x%08x",
1560 in, config->sample_rate, popcount(config->channel_mask), config->format);
1561
1562 pthread_mutex_init(&in->lock, NULL);
1563
1564 in->stream.common.get_sample_rate = in_get_sample_rate;
1565 in->stream.common.set_sample_rate = in_set_sample_rate;
1566 in->stream.common.get_buffer_size = in_get_buffer_size;
1567 in->stream.common.get_channels = in_get_channels;
1568 in->stream.common.get_format = in_get_format;
1569 in->stream.common.set_format = in_set_format;
1570 in->stream.common.standby = in_standby;
1571 in->stream.common.dump = in_dump;
1572 in->stream.common.set_parameters = in_set_parameters;
1573 in->stream.common.get_parameters = in_get_parameters;
1574 in->stream.common.add_audio_effect = in_add_audio_effect;
1575 in->stream.common.remove_audio_effect = in_remove_audio_effect;
1576 in->stream.set_gain = in_set_gain;
1577 in->stream.read = in_read;
1578 in->stream.get_input_frames_lost = in_get_input_frames_lost;
1579
1580 in->dev = adev;
1581 in->standby = true;
1582 in->config = pcm_config_capture;
1583 in->requested_rate = config->sample_rate;
1584 in->requested_channels = popcount(config->channel_mask);
1585 in->hw_frame_size = in->config.channels * sizeof(int16_t);
1586 in->remix = NULL;
1587 in->resampler = NULL;
1588 in->buffer = NULL;
1589 adev->in = in;
1590
1591 /* in-place stereo-to-mono remix since capture stream is stereo */
1592 if (in->requested_channels == 1) {
1593 ALOGV("adev_open_input_stream() stereo-to-mono remix needed");
1594 ret = setup_stereo_to_mono_input_remix(in);
1595 if (ret) {
1596 ALOGE("adev_open_input_stream() failed to setup remix %d", ret);
1597 goto err1;
1598 }
1599 }
1600
1601 if (in->requested_rate != in->config.rate) {
1602 ALOGV("adev_open_input_stream() resample needed, req=%uHz got=%uHz",
1603 in->requested_rate, in->config.rate);
1604
1605 in->buf_provider.get_next_buffer = get_next_buffer;
1606 in->buf_provider.release_buffer = release_buffer;
1607 ret = create_resampler(in->config.rate,
1608 in->requested_rate,
1609 in->requested_channels,
1610 RESAMPLER_QUALITY_DEFAULT,
1611 &in->buf_provider,
1612 &in->resampler);
1613 if (ret) {
1614 ALOGE("adev_open_input_stream() failed to create resampler %d", ret);
1615 goto err2;
1616 }
1617 }
1618
1619 /*
1620 * buffer size needs to be enough to allow stereo-to-mono remix
1621 * and resample if needed
1622 */
1623 if (in->resampler || in->remix) {
1624 buffer_size = in->config.period_size * in->hw_frame_size;
1625 if (in->resampler)
1626 buffer_size *= 2;
1627 if (in->remix)
1628 buffer_size *= 2;
1629
1630 in->buffer = malloc(buffer_size);
1631 if (!in->buffer) {
1632 ret = -ENOMEM;
1633 goto err3;
1634 }
1635 }
1636
1637 *stream_in = &in->stream;
1638
1639 return 0;
1640
1641 err3:
1642 release_resampler(in->resampler);
1643 err2:
1644 free(in->remix);
1645 err1:
1646 free(in);
1647 return ret;
1648}
1649
1650static void adev_close_input_stream(struct audio_hw_device *dev,
1651 struct audio_stream_in *stream)
1652{
1653 struct j6_audio_device *adev = (struct j6_audio_device *)dev;
1654 struct j6_stream_in *in = (struct j6_stream_in *)(stream);
1655
1656 ALOGV("adev_close_input_stream() stream=%p", stream);
1657
1658 in_standby(&stream->common);
1659
1660 if (in->resampler)
1661 release_resampler(in->resampler);
1662
1663 if (in->remix)
1664 free(in->remix);
1665
1666 free(in->buffer);
1667 free(in);
1668 adev->in = NULL;
1669}
1670
1671static int adev_dump(const audio_hw_device_t *device, int fd)
1672{
1673 UNUSED(device);
1674 UNUSED(fd);
1675
1676 return 0;
1677}
1678
1679static int adev_close(hw_device_t *device)
1680{
1681 struct j6_audio_device *adev = (struct j6_audio_device *)device;
1682
1683 ALOGI("adev_close()");
1684
1685 audio_route_free(adev->route);
1686 free(device);
1687
1688 return 0;
1689}
1690
1691static int adev_open(const hw_module_t* module, const char* name,
1692 hw_device_t** device)
1693{
1694 struct j6_audio_device *adev;
1695
1696 ALOGI("adev_open() %s", name);
1697
1698 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
1699 return -EINVAL;
1700
1701 adev = (struct j6_audio_device*)calloc(1, sizeof(struct j6_audio_device));
1702 if (!adev)
1703 return -ENOMEM;
1704
1705 pthread_mutex_init(&adev->lock, NULL);
1706
1707 adev->device.common.tag = HARDWARE_DEVICE_TAG;
1708 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
1709 adev->device.common.module = (struct hw_module_t *) module;
1710 adev->device.common.close = adev_close;
1711
1712 adev->device.init_check = adev_init_check;
1713 adev->device.set_voice_volume = adev_set_voice_volume;
1714 adev->device.set_master_volume = adev_set_master_volume;
1715 adev->device.get_master_volume = adev_get_master_volume;
1716 adev->device.set_master_mute = adev_set_master_mute;
1717 adev->device.get_master_mute = adev_get_master_mute;
1718 adev->device.set_mode = adev_set_mode;
1719 adev->device.set_mic_mute = adev_set_mic_mute;
1720 adev->device.get_mic_mute = adev_get_mic_mute;
1721 adev->device.set_parameters = adev_set_parameters;
1722 adev->device.get_parameters = adev_get_parameters;
1723 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
1724 adev->device.open_output_stream = adev_open_output_stream;
1725 adev->device.close_output_stream = adev_close_output_stream;
1726 adev->device.open_input_stream = adev_open_input_stream;
1727 adev->device.close_input_stream = adev_close_input_stream;
1728 adev->device.dump = adev_dump;
1729
1730 adev->in_device = AUDIO_DEVICE_IN_BUILTIN_MIC;
1731 adev->out_device = AUDIO_DEVICE_OUT_SPEAKER;
1732 adev->card = 0;
1733 adev->in_port = 0;
1734 adev->out_port = 0;
1735 ALOGI("Media card is hw:%d\n", adev->card);
1736 adev->bt_card=2;
1737 adev->bt_port = 0;
1738 ALOGI("Bluetooth SCO card is hw:%d\n", adev->bt_card);
1739
1740 adev->mic_mute = false;
1741 adev->in_call = false;
1742 adev->mode = AUDIO_MODE_NORMAL;
1743
1744 adev->route = audio_route_init(adev->card, NULL);
1745 if (!adev->route) {
1746 ALOGE("Unable to initialize audio routes");
1747 free(adev);
1748 return -EINVAL;
1749 }
1750
1751 *device = &adev->device.common;
1752
1753 return 0;
1754}
1755
1756static struct hw_module_methods_t hal_module_methods = {
1757 .open = adev_open,
1758};
1759
1760struct audio_module HAL_MODULE_INFO_SYM = {
1761 .common = {
1762 .tag = HARDWARE_MODULE_TAG,
1763 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
1764 .hal_api_version = HARDWARE_HAL_API_VERSION,
1765 .id = AUDIO_HARDWARE_MODULE_ID,
1766 .name = "Jacinto6 Audio HAL",
1767 .author = "Texas Instruments Inc.",
1768 .methods = &hal_module_methods,
1769 },
1770};
diff --git a/audio/primary/mixer_paths.xml b/audio/primary/mixer_paths.xml
new file mode 100644
index 0000000..b872afa
--- /dev/null
+++ b/audio/primary/mixer_paths.xml
@@ -0,0 +1,31 @@
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</mixer>
diff --git a/bluetooth/bdroid_buildcfg.h b/bluetooth/bdroid_buildcfg.h
new file mode 100644
index 0000000..a45ac86
--- /dev/null
+++ b/bluetooth/bdroid_buildcfg.h
@@ -0,0 +1,28 @@
1/*
2 * Copyright (C) 2012 Texas Instruments Inc.
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 _BDROID_BUILDCFG_H
18#define _BDROID_BUILDCFG_H
19
20#define BTM_DEF_LOCAL_NAME "AM57x"
21
22/* Handsfree device */
23#define BTA_DM_COD {0x20, 0x04, 0x08}
24
25/* Enable A2DP sink */
26#define BTA_AV_SINK_INCLUDED TRUE
27
28#endif
diff --git a/bootanimation.zip b/bootanimation.zip
new file mode 100644
index 0000000..938ceae
--- /dev/null
+++ b/bootanimation.zip
Binary files differ
diff --git a/device.mk b/device.mk
new file mode 100644
index 0000000..d044d59
--- /dev/null
+++ b/device.mk
@@ -0,0 +1,154 @@
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# Audio Post Processing Engine (APPE)
18APPE_AUDIO := false
19
20ifeq ($(TARGET_PREBUILT_KERNEL),)
21LOCAL_KERNEL := device/ti/am43xevm/kernel
22else
23LOCAL_KERNEL := $(TARGET_PREBUILT_KERNEL)
24endif
25
26PRODUCT_COPY_FILES := \
27 $(LOCAL_KERNEL):kernel \
28 device/ti/am43xevm/tablet_core_hardware_am43xevm.xml:system/etc/permissions/tablet_core_hardware_am43xevm.xml \
29 device/ti/am43xevm/init.am43xevmboard.rc:root/init.am43xevmboard.rc \
30 device/ti/am43xevm/init.am43xevmboard.usb.rc:root/init.am43xevmboard.usb.rc \
31 device/ti/am43xevm/ueventd.am43xevmboard.rc:root/ueventd.am43xevmboard.rc \
32 device/ti/am43xevm/fstab.am43xevmboard:root/fstab.am43xevmboard \
33 device/ti/am43xevm/media_profiles.xml:system/etc/media_profiles.xml \
34 device/ti/am43xevm/media_codecs.xml:system/etc/media_codecs.xml \
35 device/ti/am43xevm/media_codecs_performance.xml:system/etc/media_codecs_performance.xml \
36 frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:system/etc/media_codecs_google_audio.xml \
37 frameworks/av/media/libstagefright/data/media_codecs_google_video.xml:system/etc/media_codecs_google_video.xml \
38 frameworks/native/data/etc/android.hardware.wifi.xml:system/etc/permissions/android.hardware.wifi.xml \
39 frameworks/native/data/etc/android.hardware.wifi.direct.xml:system/etc/permissions/android.hardware.wifi.direct.xml \
40 frameworks/native/data/etc/android.hardware.usb.host.xml:system/etc/permissions/android.hardware.usb.host.xml \
41 frameworks/native/data/etc/android.hardware.usb.accessory.xml:system/etc/permissions/android.hardware.usb.accessory.xml \
42 frameworks/native/data/etc/android.hardware.ethernet.xml:system/etc/permissions/android.hardware.ethernet.xml \
43 device/ti/am43xevm/pixcir_tangoc.idc:system/usr/idc/pixcir_tangoc.idc \
44
45# These are the hardware-specific features
46PRODUCT_COPY_FILES += \
47 frameworks/native/data/etc/android.hardware.camera.xml:system/etc/permissions/android.hardware.camera.xml
48
49# Audio
50ifeq ($(APPE_AUDIO),true)
51PRODUCT_COPY_FILES += \
52 hardware/ti/radio/vis_sdk/packages/android/hal/mixer_paths.xml:system/etc/mixer_paths.xml
53else
54PRODUCT_COPY_FILES += \
55 device/ti/am43xevm/audio/primary/mixer_paths.xml:system/etc/mixer_paths.xml
56# device/ti/am43xevm/audio/primary/mixer_paths.xml:system/etc/mixer_paths.xml \
57# device/ti/am43xevm/audio/jamr3/jamr3_mixer_paths.xml:system/etc/jamr3_mixer_paths.xml
58endif
59
60PRODUCT_COPY_FILES += \
61 device/ti/am43xevm/audio/audio_policy.conf:system/etc/audio_policy.conf
62
63# cpuset configuration
64PRODUCT_COPY_FILES += \
65 device/ti/am43xevm/init.am43xevmboard.cpuset.sh:system/bin/init.am43xevmboard.cpuset.sh
66
67
68PRODUCT_PROPERTY_OVERRIDES := \
69 hwui.render_dirty_regions=false
70
71PRODUCT_DEFAULT_PROPERTY_OVERRIDES += \
72 persist.sys.usb.config=mtp
73
74PRODUCT_PROPERTY_OVERRIDES += \
75 ro.opengles.version=131072
76
77PRODUCT_CHARACTERISTICS := tablet,nosdcard
78
79DEVICE_PACKAGE_OVERLAYS := \
80 device/ti/am43xevm/overlay
81
82PRODUCT_PACKAGES += \
83 com.android.future.usb.accessory
84
85PRODUCT_PROPERTY_OVERRIDES += \
86 ro.sf.lcd_density=120
87
88# WI-Fi
89# PRODUCT_PACKAGES += \
90 wpa_supplicant \
91 wpa_supplicant.conf \
92 wpa_supplicant_overlay.conf \
93 libwpa_client \
94 hostapd \
95 hostapd.conf \
96 dhcpcd.conf \
97 wifical.sh \
98 TQS_D_1.7.ini \
99 TQS_D_1.7_127x.ini \
100 crda \
101 regulatory.bin \
102 wlconf
103
104PRODUCT_PACKAGES += \
105 LegacyCamera \
106 camera_test \
107 ion_tiler_test \
108 iontest \
109 ion_ti_test2 \
110 vpetest \
111 modetest \
112 libdrm
113
114# Audio HAL modules
115PRODUCT_PACKAGES += audio.primary.am57x
116PRODUCT_PACKAGES += audio.hdmi.am57x
117
118# JAMR3 Audio HAL module
119# ifneq ($(APPE_AUDIO),true)
120# PRODUCT_PACKAGES += audio.jamr3.am57x
121# endif
122
123# BlueDroid a2dp Audio HAL module
124PRODUCT_PACKAGES += audio.a2dp.default
125# Remote submix
126PRODUCT_PACKAGES += audio.r_submix.default
127
128PRODUCT_PACKAGES += \
129 tinymix \
130 tinyplay \
131 tinycap
132
133# Radio
134# PRODUCT_PACKAGES += \
135 RadioApp \
136 lad_dra7xx \
137 libtiipc \
138 libtiipcutils \
139 libtitransportrpmsg
140
141# Launcher3
142PRODUCT_PACKAGES += Launcher3
143
144# Enable AAC 5.1 decode (decoder)
145PRODUCT_PROPERTY_OVERRIDES += \
146 media.aac_51_output_enabled=true
147
148$(call inherit-product, frameworks/native/build/tablet-7in-hdpi-1024-dalvik-heap.mk)
149$(call inherit-product-if-exists, hardware/ti/dra7xx/am57x.mk)
150#$(call inherit-product-if-exists, hardware/ti/wpan/ti-wpan-products.mk)
151$(call inherit-product-if-exists, device/ti/proprietary-open/jacinto6/ti-jacinto6-vendor.mk)
152#$(call inherit-product-if-exists, device/ti/proprietary-open/jacinto6/ducati-full_jacinto6evm.mk)
153#$(call inherit-product-if-exists, device/ti/proprietary-open/wl12xx/wlan/wl12xx-wlan-fw-products.mk)
154#$(call inherit-product-if-exists, device/ti/proprietary-open/wl12xx/wpan/wl12xx-wpan-fw-products.mk)
diff --git a/egl.cfg b/egl.cfg
new file mode 100644
index 0000000..3c5c590
--- /dev/null
+++ b/egl.cfg
@@ -0,0 +1,2 @@
10 0 android
20 1 POWERVR_SGX530_125
diff --git a/fastboot.sh b/fastboot.sh
new file mode 100755
index 0000000..240d410
--- /dev/null
+++ b/fastboot.sh
@@ -0,0 +1,253 @@
1#!/bin/bash
2
3usage ()
4{
5 echo "Usage: sudo fastboot.sh <options>";
6 echo "options:";
7 echo " --help Show this message and exit"
8 exit 1;
9}
10
11#no args case
12if [ "$1" = "--help" ] ; then
13 usage
14fi
15
16# Pre-packaged DB
17export FASTBOOT=${FASTBOOT-"./fastboot"}
18export PRODUCT_OUT=${PRODUCT_OUT-"./"}
19export LD_LIBRARY_PATH=./
20
21echo "Fastboot: $FASTBOOT"
22echo "Image location: $PRODUCT_OUT"
23
24
25# =============================================================================
26# pre-run
27# =============================================================================
28
29# Verify fastboot program is available
30# Verify user permission to run fastboot
31# Verify fastboot detects a device, otherwise exit
32if [ -f ${FASTBOOT} ]; then
33 fastboot_status=`${FASTBOOT} devices 2>&1`
34 if [ `echo $fastboot_status | grep -wc "no permissions"` -gt 0 ]; then
35 cat <<-EOF >&2
36 -------------------------------------------
37 Fastboot requires administrator permissions
38 Please run the script as root or create a
39 fastboot udev rule, e.g:
40
41 % cat /etc/udev/rules.d/99_android.rules
42 SUBSYSTEM=="usb",
43 SYSFS{idVendor}=="0451"
44 OWNER="<username>"
45 GROUP="adm"
46 -------------------------------------------
47 EOF
48 exit 1
49 elif [ "X$fastboot_status" = "X" ]; then
50 echo "No device detected. Please ensure that" \
51 "fastboot is running on the target device"
52 exit -1;
53 else
54 device=`echo $fastboot_status | awk '{print$1}'`
55 echo -e "\nFastboot - device detected: $device\n"
56 fi
57else
58 echo "Error: fastboot is not available at ${FASTBOOT}"
59 exit -1;
60fi
61
62## poll the board to find out its configuration
63#product=`${FASTBOOT} getvar product 2>&1 | grep product | awk '{print$2}'`
64cpu=`${FASTBOOT} getvar cpu 2>&1 | grep cpu | awk '{print$2}'`
65cputype=`${FASTBOOT} getvar secure 2>&1 | grep secure | awk '{print$2}'`
66boardrev=`${FASTBOOT} getvar board_rev 2>&1 | grep board_rev | awk '{print$2}'`
67
68
69# Make EMU = HS
70if [ ${cputype} = "EMU" ] || [ ${cputype} = "HS" ]; then
71 cputype="HS"
72 xloader="${PRODUCT_OUT}${cputype}_QSPI_MLO"
73 uboot="${PRODUCT_OUT}${cputype}_u-boot.img"
74# If fastboot does not support getvar default to GP
75elif [ ${cputype} = "" ] || [ ${cputype} = "GP" ]; then
76 cputype="GP"
77 xloader="${PRODUCT_OUT}${cputype}_MLO"
78 uboot="${PRODUCT_OUT}u-boot.img"
79fi
80
81# Based on cpu, decide the dtb to flash, default fall back to J6 and LCD 10
82if [ ${cpu} = "J6ECO" ]; then
83 if [ ${boardrev} = "C" ]; then
84 environment="${PRODUCT_OUT}dra72-evm-lcd-osd.dtb"
85 elif [ ${boardrev} = "1.3A" ]; then
86 environment="${PRODUCT_OUT}am571x-idk-lcd-osd101t2587.dtb"
87 else
88 environment="${PRODUCT_OUT}dra72-evm-lcd10.dtb"
89 fi
90else
91 if [ ${boardrev} = "H" ]; then
92 environment="${PRODUCT_OUT}dra7-evm-lcd-osd.dtb"
93 else
94 environment="${PRODUCT_OUT}am57xx-evm-reva3.dtb"
95 fi
96fi
97
98if [ ${cpu} = "J6" ]; then
99 if [ ${boardrev} = "A.30" ]; then
100 environment="${PRODUCT_OUT}am57xx-evm-reva3.dtb"
101 elif [ ${boardrev} = "1.3A" ]; then
102 environment="${PRODUCT_OUT}am572x-idk-lcd-osd.dtb"
103 elif [ ${boardrev} = "B.10" ]; then
104 environment="${PRODUCT_OUT}am57xx-beagle-x15-revb1.dtb"
105 fi
106fi
107
108# Create the filename
109bootimg="${PRODUCT_OUT}boot.img"
110systemimg="${PRODUCT_OUT}system.img"
111userdataimg="${PRODUCT_OUT}userdata.img"
112cacheimg="${PRODUCT_OUT}cache.img"
113recoveryimg="${PRODUCT_OUT}recovery.img"
114
115
116# Verify that all the files required for the fastboot flash
117# process are available
118
119if [ ! -e "${bootimg}" ] ; then
120 echo "Missing ${bootimg}"
121 exit -1;
122fi
123if [ ! -e "$xloader" ] ; then
124 echo "Missing ${xloader}"
125 exit -1;
126fi
127if [ ! -e "${uboot}" ] ; then
128 echo "Missing ${uboot}"
129 exit -1;
130fi
131if [ ! -e "${environment}" ] ; then
132 echo "Missing ${environment}"
133 exit -1;
134else
135 echo "DTB = ${environment}"
136fi
137if [ ! -e "${systemimg}" ] ; then
138 echo "Missing ${systemimg}"
139 exit -1;
140fi
141if [ ! -e "${userdataimg}" ] ; then
142 echo "Missing ${userdataimg}"
143 exit -1;
144fi
145if [ ! -e "${cacheimg}" ] ; then
146 echo "Missing ${cacheimg}"
147 exit -1;
148fi
149if [ ! -e "${recoveryimg}" ] ; then
150 echo "Missing ${recoveryimg}"
151 exit -1;
152fi